我正在尝试让服务器端/同构渲染与react-router一起响应应用程序。
我的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时,它只需在node
上调用server.js
。服务器正常启动,但包括/test
在内的所有请求都以404s的形式返回。
我console.log是req.url,它正在返回正确的url。我为“routes”文件做了同样的事情,它肯定找到了正确的文件。以下是这些日志的输出:
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.我认为我正确地遵循了示例,但我不确定我哪里出错了。
答案 0 :(得分:1)
经过长时间的调试后,我发现了类似的问题 解决了这个问题,下面是我改变了几点 申请: -
i)首先,您的测试组件应返回一个正确的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:路由})与res.status('200')的组合.send(ReactDOM.renderToString(&lt; RoutingContext {。 ..renderProps} /&GT));
b)匹配({routes: routes })与res.status('200')的组合.send(ReactDOM.renderToString(&lt; RouterContext {。 ..renderProps} /&GT));
c)匹配({routes: routes.default })与res.status('200')的组合.send(ReactDOM.renderToString(&lt; RoutingContext ) {...} renderProps /&GT));
d)匹配({routes: routes.default })与res.status('200')的组合.send(ReactDOM.renderToString(&lt; RouterContext ) {...} renderProps /&GT));