2016-01-13 121 views
0

一切都是关于同构应用。我在服务器端使用Reactreact-router模块进行路由,并在浏览器控制台中发出以下警告。ReactJS反应路由器服务器渲染问题

警告:渲染(...):用新的 根组件替换呈现React渲染的子项。如果您打算更新此节点的子节点 ,则应该让现有子节点更新其状态,并且 会呈现新组件而不是调用ReactDOM.render。

<Route path="/" component={App} > 
    <IndexRoute component={Home} /> 
</Route> 

应用组件:

我有以下航线架构上后端定义

module.exports = React.createClass({ 
    render : function() { 
    return <html> 
     <head></head> 
     <body>   
     <div id="container"> 
      { this.props.children } 
     </div>   
     <script src="/app/bundle.js"></script> 
     </body> 
    </html> 
    } 
}); 

首页组件:

module.exports = React.createClass({ 
    render : function() { 
    return <div>Any content here</div> 
    } 
}); 

我在使用之后前端

ReactDOM.render(<Home />, document.getElementById('container')); 

可能的解决方案: 如果我理解正确,如果我可以使应用程序组件作为静态标记(renderToStaticMarkup)和家庭组成的字符串(renderToString),那么这将是确定。

是否可以通过react-router实现类似的功能?

+0

你是否搜索过“同构反应”? –

+1

@HenrikAndersson很多 –

+0

我想用React呈现App组件,而不是使用纯html。 –

回答

3

假设RR 1.03,您的路由配置看起来很好。

您的应用程序组件应该是这样的:

module.exports = React.createClass({ 
    render : function() { 
    return <html> 
     <head></head> 
     <body>   
     <div id="container"> 
      {React.cloneElement(this.props.children, 
      { 
       anyOtherPropsHere: 'blablah' 
      } 
     )} 
     </div>   
     <script src="/app/bundle.js"></script> 
     </body> 
    </html> 
    } 
}); 

你的服务器响应 - >渲染应该是这个样子。 (从documentation拍摄)

import { renderToString } from 'react-dom/server' 
import { match, RouterContext } from 'react-router' 
import routes from './routes' 

serve((req, res) => { 
    // Note that req.url here should be the full URL path from 
    // the original request, including the query string. 
    match({ routes, location: req.url }, (error, redirectLocation, renderProps) => { 
    if (error) { 
     res.status(500).send(error.message) 
    } else if (redirectLocation) { 
     res.redirect(302, redirectLocation.pathname + redirectLocation.search) 
    } else if (renderProps) { 
     // You can also check renderProps.components or renderProps.routes for 
     // your "not found" component or route respectively, and send a 404 as 
     // below, if you're using a catch-all route. 
     res.status(200).send(renderToString(<RouterContext {...renderProps} />)) 
    } else { 
     res.status(404).send('Not found') 
    } 
    }) 
}) 

最后,在客户方负载的地方,做这样的事情。本例中已添加history库以提供帮助。

import React from 'react'; 
import ReactDOM from 'react-dom'; 
import { Router, Route, match, RoutingContext } from 'react-router'; 
import history from 'utils/history'; 
import AppRoutes from '/app/AppRoutes'; 

// use this function to return a Route component with the right props 
function createFluxComponent(Component, props) { 
    props = Object.assign(props, { 
     flux: window.flux.or.whatevs 
    }); 

    return <Component {...props} />; 
} 

// add a global history listener perhaps? 
history.listen(function(location) { 
    console.log('Transition to--------------', location.pathname); 
}); 

// add window.router polyfill for transitionTo 
window.router = { 
    transitionTo: function(t) { 
     return history.pushState(null, t); 
    } 
}; 

// render your routing configuration, history and flux as props 
ReactDOM.render(<Router createElement={createFluxComponent} history={history} routes={AppRoutes}/>, document); 

最重要的是你使用RouterContext渲染字符串并在服务器端渲染道具。您从RR匹配函数获取renderProps,该函数将根据配置运行您的路由并在renderProps中生成正确的组件。然后,您只需使用Router元素和路由器配置将客户端呈现给文档。这有意义吗?它应该没有任何不变地工作。

+1

谢谢,它帮助我解决了我的问题! –

+1

如果答案有帮助,您能否将其标记为已接受? – nacmartin