在服务器上渲染反应
rendering react on server
我一直在努力弄清楚如何在服务器上做出反应 (node/express),最后找到了一个足够简单的教程来理解发生了什么。但是现在,在设置完所有内容后,我在 React.render
方法中遇到错误:
这是我的组件文件:
var React = require('react');
var box = React.createClass({
render: function() {
return (
<div style='padding: 10px'>
this.props.text
</div>
);
}
});
React.render(<box text='testing server side'/>, document.body);
module.exports = box;
当我 运行 npm start
:
时出现错误
document is not defined
我该如何解决这个问题?我需要还是不需要 render 方法?
为了提供更多上下文,另一个组件需要此 box
组件:
var React = require('react');
var Box = require('../react-jsx/box.js'); //this is the box component
var Component = React.createClass({
render: function() {
return (
<html>
<head>
<title>
React Server Rendering
</title>
</head>
<body>
<Box text='testing'/>
<script src="public/bundle.js"></script>
</body>
</html>
);
}
});
module.exports = Component;
这一切都在 index.js
中使用
require('node-jsx').install();
var React = require('react');
var Component = require('../custom-modules/test-react-server-module.js');
var express = require('express');
var router = express.Router();
router.get('/react', function(req, res, next) {
var markup = React.renderToString(Component());
res.send(markup);
});
module.exports = router;
如果我删除渲染方法,我会在浏览器中收到此错误:
Cannot read property '__reactAutoBindMap' of undefined
我看到有人说可能是因为 jsx transformer 太旧了,但我想我有最新版本
我没主意了
您需要在服务器环境中使用react-dom/server
包的renderToString功能。这将 return HTML 作为一个字符串,您可以在您的明确回复中发送。
首先,我建议您更新您的 React 版本。当前版本暴露了两个不同的Top-Level API:React,一般用于创建组件和ReactDOM,它公开了要在应用的顶层使用的 DOM 特定方法。
这里有几点要指出:
您正在尝试 运行 一段本应仅在浏览器中执行的代码。 NodeJS 中没有 document。我建议使用 webpack
打包此组件文件并在浏览器上提供它们。
对于同构 React 应用程序,您需要有一个 client.js
文件来调用您尝试在 index.js
中渲染的相同组件的渲染函数。明白了吗?
了解 ReactDOM.render
,如文档所述:
Render a ReactElement into the DOM in the supplied container and return a reference to the component (or returns null for stateless components).
If the ReactElement was previously rendered into container, this will
perform an update on it and only mutate the DOM as necessary to
reflect the latest React component.
请再次记住,ReactDOM.render 应该只使用几次,并且通常在您的应用程序的顶层使用一次。
话虽如此,您的 box.js
应该如下所示:
var React = require('react');
var box = React.createClass({
render: function() {
return (
<div style='padding: 10px'>
this.props.text
</div>
);
}
});
module.exports = box;
要使其正常工作,您需要创建一个主要组件 main-component-file.js
:
var React = require('react');
var Box = require('../react-jsx/box.js'); //this is the box component
var Component = React.createClass({
render: function() {
return (
<html>
<head>
<title>
React Server Rendering
</title>
</head>
<body>
<Box text='testing'/>
<script src="public/bundle.js"></script>
</body>
</html>
);
}
});
module.exports = Component;
在您的 bundle.js
中,您需要确保正在调用它,以便主要组件尝试重新渲染:
var React = require('react');
var ReactDOM = require('react-dom');
var Component = require('main-component-file.js');
ReactDOM.render(<Component/>, document.body);
最后但同样重要的是:index.js
,服务器文件。将 React.renderToString
更改为 ReactDOMServer.renderToString
,从您的主要组件创建一个 React 元素并使用它:
var element = React.createElement(Component)
router.get('/react', function(req, res, next) {
var markup = ReactDOMServer.renderToString(element);
res.send(markup);
});
不要忘记在 index.js
中包含 npm 包 react-dom/server
。
文章中使用的参考资料:
你应该删除这个
React.render(<box text='testing server side'/>, document.body);
没有这个必要。你实际上是在告诉 React 做的是当场渲染它。
document.body
尚不存在,因为您正在服务器端呈现它,您也不需要它,因为您根据 [=] 中的请求在 renderToString
函数中呈现组件13=]。 (我也认为@PeterLyons 是正确的,所以也看看他的回答)。
此外,如果您仅将 React 严格用于视图,则可能需要查看 express-react-views。他们有一个关于如何将 React 与 Express 结合使用的很好的教程,您基本上只能将其用于服务器端渲染。我认为它不像使用 react-router
那样理想,具体取决于您正在构建的内容,但它说明了 React 如何处理服务器端渲染并与 Express 一起工作。
我一直在努力弄清楚如何在服务器上做出反应 (node/express),最后找到了一个足够简单的教程来理解发生了什么。但是现在,在设置完所有内容后,我在 React.render
方法中遇到错误:
这是我的组件文件:
var React = require('react');
var box = React.createClass({
render: function() {
return (
<div style='padding: 10px'>
this.props.text
</div>
);
}
});
React.render(<box text='testing server side'/>, document.body);
module.exports = box;
当我 运行 npm start
:
document is not defined
我该如何解决这个问题?我需要还是不需要 render 方法?
为了提供更多上下文,另一个组件需要此 box
组件:
var React = require('react');
var Box = require('../react-jsx/box.js'); //this is the box component
var Component = React.createClass({
render: function() {
return (
<html>
<head>
<title>
React Server Rendering
</title>
</head>
<body>
<Box text='testing'/>
<script src="public/bundle.js"></script>
</body>
</html>
);
}
});
module.exports = Component;
这一切都在 index.js
中使用require('node-jsx').install();
var React = require('react');
var Component = require('../custom-modules/test-react-server-module.js');
var express = require('express');
var router = express.Router();
router.get('/react', function(req, res, next) {
var markup = React.renderToString(Component());
res.send(markup);
});
module.exports = router;
如果我删除渲染方法,我会在浏览器中收到此错误:
Cannot read property '__reactAutoBindMap' of undefined
我看到有人说可能是因为 jsx transformer 太旧了,但我想我有最新版本
我没主意了
您需要在服务器环境中使用react-dom/server
包的renderToString功能。这将 return HTML 作为一个字符串,您可以在您的明确回复中发送。
首先,我建议您更新您的 React 版本。当前版本暴露了两个不同的Top-Level API:React,一般用于创建组件和ReactDOM,它公开了要在应用的顶层使用的 DOM 特定方法。
这里有几点要指出:
您正在尝试 运行 一段本应仅在浏览器中执行的代码。 NodeJS 中没有 document。我建议使用
webpack
打包此组件文件并在浏览器上提供它们。对于同构 React 应用程序,您需要有一个
client.js
文件来调用您尝试在index.js
中渲染的相同组件的渲染函数。明白了吗?
了解 ReactDOM.render
,如文档所述:
Render a ReactElement into the DOM in the supplied container and return a reference to the component (or returns null for stateless components).
If the ReactElement was previously rendered into container, this will perform an update on it and only mutate the DOM as necessary to reflect the latest React component.
请再次记住,ReactDOM.render 应该只使用几次,并且通常在您的应用程序的顶层使用一次。
话虽如此,您的 box.js
应该如下所示:
var React = require('react');
var box = React.createClass({
render: function() {
return (
<div style='padding: 10px'>
this.props.text
</div>
);
}
});
module.exports = box;
要使其正常工作,您需要创建一个主要组件 main-component-file.js
:
var React = require('react');
var Box = require('../react-jsx/box.js'); //this is the box component
var Component = React.createClass({
render: function() {
return (
<html>
<head>
<title>
React Server Rendering
</title>
</head>
<body>
<Box text='testing'/>
<script src="public/bundle.js"></script>
</body>
</html>
);
}
});
module.exports = Component;
在您的 bundle.js
中,您需要确保正在调用它,以便主要组件尝试重新渲染:
var React = require('react');
var ReactDOM = require('react-dom');
var Component = require('main-component-file.js');
ReactDOM.render(<Component/>, document.body);
最后但同样重要的是:index.js
,服务器文件。将 React.renderToString
更改为 ReactDOMServer.renderToString
,从您的主要组件创建一个 React 元素并使用它:
var element = React.createElement(Component)
router.get('/react', function(req, res, next) {
var markup = ReactDOMServer.renderToString(element);
res.send(markup);
});
不要忘记在 index.js
中包含 npm 包 react-dom/server
。
文章中使用的参考资料:
你应该删除这个
React.render(<box text='testing server side'/>, document.body);
没有这个必要。你实际上是在告诉 React 做的是当场渲染它。
document.body
尚不存在,因为您正在服务器端呈现它,您也不需要它,因为您根据 [=] 中的请求在 renderToString
函数中呈现组件13=]。 (我也认为@PeterLyons 是正确的,所以也看看他的回答)。
此外,如果您仅将 React 严格用于视图,则可能需要查看 express-react-views。他们有一个关于如何将 React 与 Express 结合使用的很好的教程,您基本上只能将其用于服务器端渲染。我认为它不像使用 react-router
那样理想,具体取决于您正在构建的内容,但它说明了 React 如何处理服务器端渲染并与 Express 一起工作。