我可以使用React中的数据进行服务器渲染吗?

我正在做最近的反应。 我正在使用服务器呈现与react-router,但它只能从反应组件呈现HTML,我需要通过componentDidMount() ajax获取初始数据。

问题在于某些页面/组件,他们需要初始数据来呈现。 因此,如果用户直接访问这样的页面(通过inputurl或refresh),页面就会被破坏,因为服务器无法在没有初始数据的情况下渲染页面。

我想我可以从数据库中获取数据,并在服务器中渲染时插入到模板? 就像经典的前端模板或PHP所做的一样。

如果没有办法,渲染首页数据的最佳做法是什么?

现在我的服务器代码是这样的:

 router.get('*', function(req, res) { console.log('GET ADMIN'); match({ routes: appRoutes, location: req.originalUrl }, (error, redirectLocation, renderProps) => { if (error) { res.status(500) .send(error.message); } else if (redirectLocation) { res.status(302) .redirect(redirectLocation.pathname + redirectLocation.search); } else if (renderProps) { var content = renderToString(<RoutingContext {...renderProps}/>); var html = swig.renderFile('src/client/admin.html', { content: content }); res.status(200) .send(html); } else { res.status(404) .send('Not found'); } }); }); 

最后,我在GitHub上find了答案: https : //github.com/rackt/react-router/issues/1969#issuecomment-140988110

此方法在服务器中呈现时将所需的所有数据插入到HTML模板中,并以前端数据的forms获取context 。 所有组件都可以通过context获取数据。

我使用<DataWrapper>组件来包装原始的根应用程序组件。 在服务器端渲染时:

 data = JSON.stringify(data); // data is an object ReactDOMServer.renderToString(<DataWrapper data={data}><RoutingContext {...renderProps}/></DataWrapper>) 

<DataWrapper>是这样的:

 import React from 'react'; class DataWrapper extends React.Component { getChildContext () { return { data: this.props.data }; } render () { return this.props.children; } } DataWrapper.childContextTypes = { data: React.PropTypes.object.isRequired }; export default DataWrapper; 

在客户端:

 var data = JSON.parse(document.getElementById('data').innerHTML), history = createBrowserHistory(); ReactDOM.render(<DataWrapper data={ data }><Router history={ history }>{ routes }</Router></DataWrapper>, document.getElementById('app')); 

通过组件中的上下文获取数据:

 class someComponent extends React.Component { constructor (props, context) { super(props, context); this.state = context.data.someData; } } someComponent.contextTypes = { data: React.PropTypes.object.isRequired }; export default someComponent; 

它运作良好

使用AJAX调用进行初始化的问题是,它迫使您先渲染数据,然后在数据到达时重新渲染。

更好的方法是将数据包含在页面中,以便在初始渲染时使用。 例如

 <script> var __INITIAL_DATA__ = { /* etc */ } </script> 

是的,globals是丑陋的。 但在这种情况下是必要的。 你只用它来初始化你的React组件。 (或者如果您使用Flux,则是您的商店。)

是的,在同构/通用应用程序中,您可以在服务器端代码中使用相同的数据。 就像在PHP和其他服务器端语言。 只有你的服务器端代码不会从全局variables拉。 数据应该直接传递到您正在安装的React组件中。