详解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); } } });
内容版权声明:除非注明,否则皆为本站原创文章。