React-route 和服务端渲染——如何用数据渲染组件

React-route and server-side rendering - how to render components with data

当在服务器端呈现它们时,我已经能够传递数据以对组件做出反应,例如:

app.get('/', function (req, res, next) {
    var reactHtml = ReactDOMServer.renderToString(component({data}));
    res.render('index.jade', {reactOutput: reactHtml});
});

现在改成

server.js:

app.get('*', (req, res) => {
    // match the routes to the url
    match({ routes: routes, location: req.url }, (err, redirect, props) => {
        props.data = {q:123};
        const appHtml =  ReactDOMServer.renderToString(routerContext(props));
        res.render('index.jade', {reactOutput: appHtml});
    })
});

路由器上下文

module.exports = React.createClass({
    render: function(){return(<RouterContext {...this.props}  />)}
});

和路线

module.exports = (
    <Route path="/" component={App} {...this.props}>
        <IndexRoute component={List}/>
        <Route path="/about" component={About}/>
    </Route>
);

App.jsx

var App = React.createClass({
    render: function () {
        console.log(this.props);
        return (
            <div id="app-root" className="container">
                <Nav/>
                <h1>{this.props.q}</h1>
                {this.props.children}
                <div className="Row">
                    <div className="footer col-lg-12"></div>
                </div>
            </div>
        )
    }

});

例如,我想在我的 App 组件中从这一点 props.data = {q:123}; 获取数据,但是当我在 App 组件渲染方法中执行 console.log(this.data); 时,我有历史、位置等,但不是我的数据。无论如何,是否可以将数据 {q:123} 从 server.js 逻辑传递到组件(App 或 List 或 About)道具?

(假设我们现在总是加载一些数据)

您需要序列化您的数据并将其添加到服务器呈现的页面,例如,如果您将其作为 initialState:

传递给您的根组件
renderInitialState() {
    const innerHtml = `window.__INITIAL_STATE__ = ${JSON.stringify(this.props.initialState)}`;
    return <script dangerouslySetInnerHTML={{__html: innerHtml}} />;
}

所以:

<script>window.__INITIAL_STATE__ = JSON.stringify(yourObject);</script>

请注意,您似乎使用 jade 来呈现 "shell" 而不是 React。同样的事情适用于玉模板。

您通常会在 <body> 的底部呈现它(但在您的应用程序 js 脚本之上)。

如果您正在为您的客户端状态使用 flux,您将在创建商店时传递此对象,例如对于 redux:

const store = configureStore(window.__INITIAL_STATE__);

你的 props.data = {q:123}; 不会在任何地方被调用,因为 RouterContext 不知道如何处理它。

您传递给 match 的回调函数的三个参数是:

  1. 错误:如果发生错误,则为 javascript 错误对象,否则为 undefined
  2. redirectLocation:如果路由是重定向,则为 Location 对象, undefined否则
  3. renderProps:如果路由匹配,你应该传递给路由上下文的道具,undefined 否则。

    如果三个参数都是undefined,这意味着没有找到匹配的路由 给定位置。

要了解该机制,您可以在此处添加 console.dir

match({ routes: routes, location: req.url }, (err, redirect, props) => {
        console.dir(props);
        const appHtml =  ReactDOMServer.renderToString(routerContext(props));
        res.render('index.jade', {reactOutput: appHtml});
    })
});

console.dir(props.components) 会向您显示所有传递给渲染的组件。您还可以在此处创建一个新的反应元素并将其推送到 props.components

将数据传递到您的应用程序组件 没有商店

修改此函数使其能够检索数据,并使用新数据创建虚拟组件

routes.jsx

module.exports = function(serverData){
  var Dummy= React.createClass({
     render: function () {
       return (
         <div> customProps=serverData </div>
             );}
         });

  return(
    <Route path="/" component={App}>
        <Route path='data' component={{PonyMan: Dummy}}
        <IndexRoute component={List}/>
        <Route path="/about" component={About}/>
    </Route>
   );
}

server.jsx:

app.get('*', (req, res) => {
    myCustomData = 'I like ponies'
    const routes = createRoutes(myCustomData); //from imported routes.jsx
    match({ routes: routes, location: req.url }, (err, redirect, props) => {
        const appHtml =  ReactDOMServer.renderToString(routerContext(props));
        res.render('index.jade', {reactOutput: appHtml});
    })
});

App.js

var App = React.createClass({
    render: function () {
        return (
            <div id="app-root" className="container">
                <Nav/>
                <h1>{this.props.main}</h1>//this now shows <div>I Like Ponies</div>

                //this can still display other routes
                {this.props.children}
                <div className="Row">
                    <div className="footer col-lg-12"></div>
                </div>
            </div>
        )
    }    
});

P.S。使用 redux 商店会更容易 检查此项目以查看具有服务器端渲染的 react-router redux express mongoose 项目的一个很好的示例 https://github.com/choonkending/react-webpack-node