我有这样的服务器代码:
var data = {
scripts: scripts,
children:[<Comp1 />, <Comp2 />, <Comp3 />]
};
// keeping smaller for easier example than reality
var markup = '';
markup += '<script type="text/javascript">' +
'var PROPS = {' +
'Layout: ' + JSON.stringify(data) +
'};' +
'</script>';
markup += React.renderToString(
<Layout {...data} ></Layout>
);
所以服务器渲染一切都很好。然后,无论我尝试什么,我都会收到各种各样的警告,告诉我在运行时如何处理孩子的序列化和在浏览器中重复使用:React.render(App(window.PROPS.Layout), document.getElementById('content'));
我的许多尝试都让React抱怨我应该使用createFragment。但是当我这样做时,我仍然会遇到错误,我应该把它包起来。
我的目标是使用多个子项渲染Layout组件,并让浏览器中的React知道下面的相同元素。许多尝试也会产生此错误:
Warning: React attempted to reuse markup in a container but the checksum was invalid. This generally means that you are using server rendering and the markup generated on the server was not what the client was expecting. React injected new markup to compensate which works but you have lost many of the benefits of server rendering. Instead, figure out why the markup being generated is different on the client or server:
(client) d=".1frk89jhyio.1"></div><div data-react
(server) d=".1frk89jhyio.1"><div style="float:lef
我的客户端代码是:
var React = require('react'),
Layout = require('./components/layout');
React.render(<Layout {...PROPS.Layout} />, document.getElementById('content'));
答案 0 :(得分:0)
您不应该为这样的组件进行字符串化以便为您的客户服务。您应该再次渲染应用程序。要字符串化的内容应该只是{id: 1, name: 'limelights'}
等原始数据。
在服务器上
React.renderToString(<Layout {...data} />);
并在客户端
var data = JSON.parse(window.PROPS.data);
React.render(<Layout {...data} />, document.body);
拥有同构应用程序的关键是相同的代码在服务器和客户端上运行。
答案 1 :(得分:0)
答案是我以理论错误的方式做事。
使服务器呈现为<Layout {...data} ><Comp1 /></Layout>
将起作用。但是,当浏览器启动时,它将不会有子道具,您将丢失Comp1
。然后我试图通过像我的问题中的例子那样的道具传递孩子。实现此目的的真正方法是让服务器执行<Layout {...data} ></Layout>
。
答案的真正关键是render
Layout
方法应该直接放置孩子。我可以在渲染中使用状态(或道具,仍在计算语义差异)来确定孩子是否应该是不同的。