简体   繁体   English

反应路线和服务器端渲染-如何使用数据渲染组件

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

I've bean able to pass data to react components when rendered them at server-side like: 当在服务器端呈现组件时,我能够传递数据以响应组件:

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

Now I've changet it to 现在我将其更改为

server.js: 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});
    })
});

router context 路由器上下文

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

and routes 和路线

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

App.jsx 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>
        )
    }

});

So for example I want do get data from this point props.data = {q:123}; 因此,例如,我想从这一点获取数据props.data = {q:123}; in my App component, but when I do console.log(this.data); 在我的App组件中,但是当我执行console.log(this.data); in App component render method I've got history, location and etc, but not my data. 在App组件渲染方法中,我有历史记录,位置等信息,但没有我的数据。 Is there anyway to pass data {q:123} to component (App or List or About) props from server.js logic? 无论如何,是否有将数据{q:123}从server.js逻辑传递到组件(应用程序或列表或关于)道具的信息?

(Let's asume we always load some data for now) (假设我们现在总是加载一些数据)

You need to serialize your data and add it to the page on the server render, for example if you pass it to your root component as initialState : 您需要序列化数据并将其添加到服务器渲染的页面上,例如,如果将其作为initialState传递给根组件:

renderInitialState() {
    const innerHtml = `window.__INITIAL_STATE__ = ${JSON.stringify(this.props.initialState)}`;
    return <script dangerouslySetInnerHTML={{__html: innerHtml}} />;
}

So: 所以:

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

Note that it looks like you're using jade to render the "shell" instead of React. 注意,看起来您正在使用玉石渲染“ shell”而不是React。 So same thing applies but do it for the jade template. 因此,同样的事情适用于玉模板。

You would typically render that at the bottom of your <body> (but above your app js script). 您通常会在<body>的底部(但在应用程序js脚本上方)呈现它。

If you're using flux for your client state you would pass this object when creating your store, eg for redux: 如果您将flux用于客户状态,则在创建商店时将传递此对象,例如,用于redux:

const store = configureStore(window.__INITIAL_STATE__);

Your props.data = {q:123}; 您的props.data = {q:123}; doesn't get called anywhere, because RouterContext doesn't know what to do with it. 不会在任何地方被调用,因为RouterContext不知道如何处理它。

The three arguments to the callback function you pass to match are: 您传递来match的回调函数的三个参数是:

  1. error: A javascript Error object if an error occured, undefined otherwise. 错误:如果发生错误,则为JavaScript错误对象,否则undefined
  2. redirectLocation: A Location object if the route is a redirect, undefined otherwise redirectLocation:如果路由是重定向的,则为Location对象,否则为undefined
  3. renderProps: The props you should pass to the routing context if the route matched, undefined otherwise. renderProps:如果路由匹配,则应传递到路由上下文的props,否则undefined

    If all three parameters are undefined , this means that there was no route found matching the given location. 如果所有三个参数均未undefined ,则表示找不到与给定位置匹配的路线。

To understand the mechanism you could add console.dir here 要了解该机制,您可以在此处添加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});
    })
});

And console.dir(props.components) would show you all the components that are being passed to render. console.dir(props.components)将显示所有传递给渲染的组件。 You could also create a new react element here and push it to props.components 您还可以在此处创建一个新的react元素并将其推送到props.components

To pass data into your app component with no stores 无需存储即可 将数据传递到您的应用程序组件中

Modify this function to have the ability to retrieve data, and create dummy component with the new data 修改此功能以具有检索数据的能力,并使用新数据创建虚拟组件

routes.jsx route.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: 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 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>
        )
    }    
});

PS it would be way easier using redux stores check this project to see a good example of react-router redux express mongoose project with server side rendering https://github.com/choonkending/react-webpack-node PS,使用redux商店会更容易,检查此项目以查看带有服务器端渲染的react-router redux express猫鼬项目的好示例https://github.com/choonkending/react-webpack-node

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM