详解React 在服务端渲染的实现(3)
这将返回 Hello 组件的 HTML ,我们将其注入到 index.html 的 HTML 中,从而生成服务器上页面的完整 HTML 。
const document = data.replace(/<div id="app"><\/div>/,`<div id="app">${html}</div>`);
To start the server, update the start script in package.json and then run npm run start:
要启动服务器,请更新 `package.json` 中的起始脚本,然后运行 npm run start :
"scripts": {
"start": "webpack && babel-node server.js"
},
浏览 http://localhost:3000 查看应用程序。瞧!您的页面现在正在从服务器渲染出来了。但是有个问题,如果您在浏览器中查看页面源码,您会注意到博客文章仍未包含在回复中。这是怎么回事?如果我们在Chrome中打开网络标签,我们会看到客户端上发生API请求。

虽然我们在服务器上渲染了 React 组件,但是 API 请求在 componentWillMount 中异步生成,并且组件在请求完成之前渲染。所以即使我们已经在服务器上完成渲染,但我们只是完成了部分。事实上,React repo 有一个 issue,超过 100 条评论讨论了这个问题和各种解决方法。
在渲染之前获取数据
要解决这个问题,我们需要在渲染 Hello 组件之前确保 API 请求完成。这意味着要使 API 请求跳出 React 的组件渲染循环,并在渲染组件之前获取数据。我们将逐步介绍这一步,但您可以在GitHub上查看完整的差异。
To move data fetching before rendering, we'll install react-transmit:
要在渲染之前获取数据,我们需安装 react-transmit:
npm install react-transmit --save
React Transmit 给了我们优雅的包装器组件(通常称为“高阶组件”),用于获取在客户端和服务器上工作的数据。
这是我们使用 react-transmit 后的组件的代码:
import React from 'react';
import Butter from 'buttercms'
import Transmit from 'react-transmit';
const butter = Butter('b60a008584313ed21803780bc9208557b3b49fbb');
var Hello = React.createClass({
render: function() {
if (this.props.posts) {
return (
<div>
{this.props.posts.data.map((post) => {
return (
<div key={post.slug}>{post.title}</div>
)
})}
</div>
);
} else {
return <div>Loading...</div>;
}
}
});
export default Transmit.createContainer(Hello, {
// 必须设定 initiallVariables 和 ftagments ,否则渲染时会报错
initialVariables: {},
// 定义的方法名将成为 Transmit props 的名称
fragments: {
posts() {
return butter.post.list().then((resp) => resp.data);
}
}
});
内容版权声明:除非注明,否则皆为本站原创文章。
