服务器端未定义的renderProps / React / React-Router + Node / Express.js的同构渲染

我试图得到服务器端/同构渲染工作的反应应用程序与反应路由器一致。

我的route.js

 import React from 'react'; import { Route } from 'react-router'; import Test from './components/test'; export default ( <Route path="/test" component={ Test }> </Route> ); 

我的server.js

 'use strict'; require('babel-core/register') var path = require('path'); var express = require('express'); var logger = require('morgan'); var compression = require('compression'); var http = require('http'); var ReactDOM = require('react-dom/server'); var Router = require('react-router'); var match = Router.match; var RoutingContext = Router.RoutingContext; var routes = require('./src/routes'); var app = express(); var server; var PORT = process.env.PORT || 3000 app.use(logger('dev')); app.use(compression()); // Set path to public assets app.use(express.static(path.join(__dirname, 'public'))); app.get('*', function(req, res) { console.log('URL: ', req.url); console.log('Routes: ', routes); match({ routes: routes, location: req.url }, (error, redirectLocation, renderProps) => { console.log('Render Props: ', renderProps) if (error) { res.status(500).send(error.message) } else if (redirectLocation) { res.redirect(302, redirectLocation.pathname + redirectLocation.search); } else if (renderProps) { res.status(200).send(ReactDOM.renderToString(React.createElement(RoutingContext, renderProps))) } else { res.status(404).send('Not found') } }) }) server = http.createServer(app); server.listen('3000', () => { console.log('Express server listening on port ' + PORT); }); 

所以当我运行npm run start时,只需在server.js上调用node即可。 服务器启动正常,但所有的请求,包括/test回来为404s。

我console.log'd req.url,它正在返回正确的url。 我对“路由”文件做了相同的处理,并且确实find了正确的文件。 以下是这些日志的输出:

 Express server listening on port 3000 URL: /test Routes: { default: { '$$typeof': Symbol(react.element), type: { [Function] displayName: 'Route', createRouteFromReactElement: [Function: createRouteFromReactElement], propTypes: [Object] }, key: null, ref: null, props: { path: '/test', component: [Object] }, _owner: null, _store: {} } } Render Props: undefined GET /test 404 19.596 ms - 9 

然而, renderProps总是未定义的,并且响应返回404.我认为我正确地遵循了这些示例,但是我不确定哪里出错了。

经过长时间的debugging,我遇到了类似的问题,我发现了一些可以解决这个问题的东西,下面是我在应用程序中改变的几点:

i)首先你的testing组件应该返回一个适当的dom元素,它可以渲染,而不是只渲染组件。 您应该返回null或包含所需元素的正确容器元素。请参见下面的示例(这是我在应用程序中执行的第一个错误)。

 export default class Test extends React.Component { constructor(props) { super(props); } render () { return ( <div> <h1>opopooopppopo</h1> <p>This is your world.</p> </div> ); } } 

ii)在你的代码库中使用RouterContext而不是使用RoutingContext ,这是我的工作,这是我的代码中的主要问题。 因为RoutingContext已经在新版本的react-router中被弃用了。 这个改变解决了我的问题。

 res.status('200').send(ReactDOM.renderToString(<RouterContext {...renderProps}/>)); 

(注意:请不要忘记从react-router模块导入RouterContext。)

//从react-router导入路由器上下文的语句

 var RouterContext = Router.RouterContext; 

iii)如果以上所有的东西都不起作用 ,那么改变匹配函数使用routes.default而不是仅路由改变:匹配({routes:routes,location}匹配({routes:routes.default,location} ,如果你使用的是babel 6,这个改变是必须的。试试这个结合RoutingContext和RouterContext,因为我不知道版本的react-router和babel是你使用的,所以组合是:

a)匹配({routes: routes })与res.status('200')的组合。

b)match({routes: routes })与res.status('200')的组合。send(ReactDOM.renderToString(< RouterContext {… renderProps} />));

c)match({routes: routes.default })与res.status('200')的组合。send(ReactDOM.renderToString(< RoutingContext {… renderProps} />));

d)match({routes: routes.default })与res.status('200')的组合。