React、redux 和 react-router 服务器端渲染
React, redux, and react-router server side rendering
尝试在服务器上呈现我的 React 应用程序时,我收到以下错误:
Error: Uncaught error: Invariant Violation: Element type is invalid:
expected a string (for built-in components) or a class/function (for
composite components) but got: undefined.
这是我的 server.js 代码,为简洁起见,我删除了服务器配置。
import hapi from 'hapi';
import inert from 'inert';
import path from 'path';
import fs from 'fs';
import React from 'react';
import { ReactDOM, renderToString } from 'react-dom/server';
import { RouterContext, ReactRouter, match } from 'react-router';
import { Provider } from 'react-redux';
import routes from './src/config/routes';
import store from './src/flux/store';
...
match({routes, location: request.url.path}, function(err, redirectLocation, renderProps) {
if (err) {
reply(err.message).status(500);
} else if (redirectLocation) {
reply()
.redirect(redirectLocation.pathname + redirectLocation.search)
.code(302);
} else if (renderProps) {
var element = (
<RouterContext {...renderProps} />
);
console.log(element);
reply(renderToString(element)).code(200);
} else {
reply('Page Not Found')
}
});
正在调用 if 语句的 renderProps 块,这是抛出错误的地方。
编辑:当我从 react-router 导入后 console.log RouterContext 时,我变得不确定。
您可以在此处查看我的 package.json 版本:http://pastebin.com/mpb6XSKu
问题是我指的是 master 的最新 react-router 文档,其中提到了 "RouterContext." 在版本 1.0.2 中,它被命名为 "RoutingContext." 更改我的代码以引用后者解决了其中一个问题。这是我最终的工作同构服务器,除了呈现静态资产之外:
import hapi from 'hapi';
import inert from 'inert';
import React from 'react';
import { createStore } from 'redux';
import { ReactDOM, renderToString } from 'react-dom/server';
import { RoutingContext, ReactRouter, match } from 'react-router';
import { Provider } from 'react-redux';
import routes from './src/config/routes';
import initializeStore from './src/flux/store';
const server = new hapi.Server();
server.register(inert, err => {
if (err) {
throw err;
}
server.connection({
host: '0.0.0.0',
port: 80
});
server.route({
method: 'GET',
path: '/{path*}',
handler: function (request, reply) {
var url = request.url.path;
var matcher = {
routes,
location: request.url.path
};
match(matcher, function(err, redirectLocation, renderProps) {
if (err) {
reply(err.message).status(500);
} else if (redirectLocation) {
reply()
.redirect(redirectLocation.pathname + redirectLocation.search)
.code(302);
} else if (renderProps) {
var element = (
<Provider store={initializeStore()}>
<RoutingContext {...renderProps} />
</Provider>
);
reply(renderToString(element)).code(200);
} else {
reply('Page Not Found');
}
});
}
});
server.start(function (err) {
if (err) {
throw err;
}
console.log('Server started');
});
});
尝试在服务器上呈现我的 React 应用程序时,我收到以下错误:
Error: Uncaught error: Invariant Violation: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined.
这是我的 server.js 代码,为简洁起见,我删除了服务器配置。
import hapi from 'hapi';
import inert from 'inert';
import path from 'path';
import fs from 'fs';
import React from 'react';
import { ReactDOM, renderToString } from 'react-dom/server';
import { RouterContext, ReactRouter, match } from 'react-router';
import { Provider } from 'react-redux';
import routes from './src/config/routes';
import store from './src/flux/store';
...
match({routes, location: request.url.path}, function(err, redirectLocation, renderProps) {
if (err) {
reply(err.message).status(500);
} else if (redirectLocation) {
reply()
.redirect(redirectLocation.pathname + redirectLocation.search)
.code(302);
} else if (renderProps) {
var element = (
<RouterContext {...renderProps} />
);
console.log(element);
reply(renderToString(element)).code(200);
} else {
reply('Page Not Found')
}
});
正在调用 if 语句的 renderProps 块,这是抛出错误的地方。
编辑:当我从 react-router 导入后 console.log RouterContext 时,我变得不确定。
您可以在此处查看我的 package.json 版本:http://pastebin.com/mpb6XSKu
问题是我指的是 master 的最新 react-router 文档,其中提到了 "RouterContext." 在版本 1.0.2 中,它被命名为 "RoutingContext." 更改我的代码以引用后者解决了其中一个问题。这是我最终的工作同构服务器,除了呈现静态资产之外:
import hapi from 'hapi';
import inert from 'inert';
import React from 'react';
import { createStore } from 'redux';
import { ReactDOM, renderToString } from 'react-dom/server';
import { RoutingContext, ReactRouter, match } from 'react-router';
import { Provider } from 'react-redux';
import routes from './src/config/routes';
import initializeStore from './src/flux/store';
const server = new hapi.Server();
server.register(inert, err => {
if (err) {
throw err;
}
server.connection({
host: '0.0.0.0',
port: 80
});
server.route({
method: 'GET',
path: '/{path*}',
handler: function (request, reply) {
var url = request.url.path;
var matcher = {
routes,
location: request.url.path
};
match(matcher, function(err, redirectLocation, renderProps) {
if (err) {
reply(err.message).status(500);
} else if (redirectLocation) {
reply()
.redirect(redirectLocation.pathname + redirectLocation.search)
.code(302);
} else if (renderProps) {
var element = (
<Provider store={initializeStore()}>
<RoutingContext {...renderProps} />
</Provider>
);
reply(renderToString(element)).code(200);
} else {
reply('Page Not Found');
}
});
}
});
server.start(function (err) {
if (err) {
throw err;
}
console.log('Server started');
});
});