React-route和服务器端呈现 - 如何使用数据呈现组件

时间:2016-03-21 17:31:03

标签: node.js express reactjs react-router isomorphic-javascript

我可以在服务器端渲染数据时将数据传递给反应组件,如:

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);时,我已经获得了历史记录,位置等,但不是我的数据。无论如何,从server.js逻辑传递数据{q:123}到组件(App或List或About)道具?

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

2 个答案:

答案 0 :(得分:2)

您需要序列化数据并将其添加到服务器渲染中的页面,例如,如果您将其作为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__);

答案 1 :(得分:0)

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

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

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

    如果所有三个参数都是undefined,则表示找不到与之匹配的路径 给定位置。

  4. 要了解您可以在此处添加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)会显示传递给渲染的所有组件。您还可以在此处创建新的react元素并将其推送到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