不变违规:元素类型无效:应为字符串或类,但得到:未定义。检查`MyApp`的渲染方法

时间:2019-07-03 00:36:48

标签: javascript reactjs meteor react-router react-dom

我正在尝试从流星服务器端加载静态HTML,该服务器也使用redux和router。但是,每次我尝试使用renderToString()渲染组件时,都会出现标题中指示的错误。我在做什么错了?

我已经尝试过使用React.renderComponentToString作为可能的替代方法,但是我得到一个错误,即React.renderComponentToString不是一个函数。我还要如何通过争论?

import React from 'react';  
import {onPageLoad} from 'meteor/server-render';  
import {StaticRouter} from 'react-router';  
import {Provider} from 'react-redux';  
import {createStore, applyMiddleware} from 'redux';  
import {Helmet} from 'react-helmet';  
import rootReducer, {initialState} from '../redux/reducers';
import HomePage from '../ui/homepage/HomePage';

export default renderServerPage = onPageLoad(sink => {

  const context = {};
  const store = createStore(rootReducer, initialState, applyMiddleware(thunk));

  const MyApp = props => {
    return (
      <Provider store={store}>
        <StaticRouter location={sink.request.url} context={context}>
          <Route path="/" component={HomePage}/>
        </StaticRouter>
      </Provider>
    );
  }

  // The following line is causing the error
  sink.renderIntoElementById('app', renderToString(<MyApp />));

  const helmet = Helmet.renderStatic();

  sink.appendToHead(helmet.title.toString(
    "Afterschools, Enrichment Programs, Growth, & Experiences - Fun2Bright"
  ));

  sink.appendToBody(
    <script>
      window.__PRELOADED_STATE__ = ${JSON.stringify(preloadedState).replace(/</g, '\\u003c')}
    </script>
  );
});

我的其他尝试包括: 1)在同一文件中的范围之外创建组件,并将store和sink.request.url作为props传递

function MyApp (props) {
  const context = {};
  return (
    <Provider store={props.store}>
      <StaticRouter location={props.location} context={context}>
        <Route path="/" component={HomePage}/>
      </StaticRouter>
    </Provider>
  );
}

2)基本上在另一个文件中创建相同的组件,然后导入该组件。

3)直接将元素放入renderToString内:

sink.renderIntoElementById('app', renderToString(
    <Provider store={store}>
      <StaticRouter location={sink.request.url} context={context}>
        <Route path="/" component={HomePage}/>
      </StaticRouter>
    </Provider>
));

4)使用React.createElement而不传递任何道具:

sink.renderIntoElementById('app', renderToString(React.createElement(MyApp)));

5)注释掉以下内容只是为了查看它是否是由我的其他任何导入组件引起的

<Route path="/" component={HomePage}/>

1 个答案:

答案 0 :(得分:1)

我终于想到了这个问题。事实证明,仅使用react-router不允许我使用诸如和的DOM感知组件,因此我需要使用react-router-dom来代替。 react-router-dom还会重新导出react-router的所有导出,因此我只需要使用react-router-dom。我更改了所有要从“ react-router-dom”导入的内容:

import {Route, StaticRouter} from 'react-router-dom';
...
// inside onPageLoad
const App = props => {
    return (
      <Provider store={store}>
        <StaticRouter location={props.location} context={context}>
          <Route path="/" component={HomePage}/>
        </StaticRouter>
      </Provider>
    );
  }

sink.renderIntoElementById('app', renderToString(<App store={store} location={sink.request.url}/>));

我是从这里找到的:https://github.com/ReactTraining/react-router/issues/4648