【问题标题】:rendering react on server在服务器上渲染反应
【发布时间】:2016-03-28 06:11:49
【问题描述】:

我一直在试图弄清楚如何在服务器(节点/快递)上呈现反应,最后找到了一个足够简单的教程来了解发生了什么。但是现在,在设置完所有内容后,我在 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时出现错误:

文档未定义

我该如何解决这个问题?我需要还是不需要 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;

如果我删除渲染方法,我会在浏览器中收到此错误:

无法读取未定义的属性“__reactAutoBindMap”

我看到有人说可能是jsx转换器太旧了,但我想我有最新版本

我没有想法

【问题讨论】:

    标签: node.js express reactjs


    【解决方案1】:

    您需要在服务器环境中使用react-dom/server 包的renderToString 函数。这会将 HTML 作为字符串返回,您可以将其发送到您的快速响应中。

    【讨论】:

    • 我明白了,您能否更改我的代码的相关部分并告诉我我必须做什么?或者这里有个问题,我只需要 index.js 中的 react-dom 包吗?
    【解决方案2】:

    首先,我建议更新您的 React 版本。当前版本公开了两个不同的顶级 API:React,通常用于创建组件和 ReactDOM,公开要在顶级使用的特定于 DOM 的方法您的应用程序。

    这里有一点需要指出:

    • 您正在尝试运行本应仅在浏览器上执行的代码。 NodeJS 中没有document。我建议使用webpack 打包此组件文件并在浏览器上提供它们。

    • 对于同构 React 应用程序,您需要有一个 client.js 文件,该文件为您尝试在 index.js 中渲染的同一组件调用渲染函数。明白了吗?

    了解ReactDOM.render,如文档所述:

    在提供的容器中将 ReactElement 渲染到 DOM 中并返回对组件的引用(或为无状态组件返回 null)。

    如果 ReactElement 之前被渲染到容器中,这将 对其执行更新并仅根据需要更改 DOM 反映最新的 React 组件。

    请再次记住,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 Element 并使用它:

    var element = React.createElement(Component)
    router.get('/react', function(req, res, next) {
      var markup = ReactDOMServer.renderToString(element);
      res.send(markup);
    });
    

    不要忘记将 npm 包 react-dom/server 包含在您的 index.js 中。

    文章中使用的参考文献:

    【讨论】:

    • 您好,非常感谢您的解释。我用 nom 为 react-dom/server 安装什么包? npm install react-dom/server?
    • 好的,知道了。对不起,还有一个问题。所以要使用 ReactDOM.render 我还需要另一个包吗?或者我只需要 react 就可以访问 reactDOM?
    • 哦等等,应该是我刚刚安装的 reactDom 包吧?
    • 大声笑再次打扰您,但我仍然对一件事感到困惑。当我将 react.render 交换为 reactDOM.render 时,它应该是什么样子?我要删除“文档”引用吗?
    • 更新,因为 FB 现在说 React.createFactory() 被认为是“旧版”。 reactjs.org/docs/react-api.html#createfactoryReact.createElement() 直接在 React 16 中工作
    【解决方案3】:

    你应该删除这个

    React.render(<box text='testing server side'/>, document.body);
    

    没有必要。您实际上是在告诉 React 做的就是在当时和那里渲染它。

    document.body 还不存在,因为您正在服务器端渲染它,而且您也不需要它,因为您根据router 中的请求在renderToString 函数中渲染组件。 (我也认为@PeterLyons 是正确的,所以也看看他的回答)。

    此外,如果您严格将 React 仅用于视图,您可能需要查看 express-react-views。他们有一个关于如何使用 React 和 Express 的很好的教程,你基本上只能将它用于服务器端渲染。我认为它不像使用 react-router 那样理想,具体取决于您正在构建的内容,但它说明了 React 如何处理服务器端渲染并与 Express 配合使用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-01-14
      • 1970-01-01
      • 2015-05-09
      • 2019-02-09
      • 2020-04-19
      • 2018-10-02
      • 2020-06-27
      • 2016-03-12
      相关资源
      最近更新 更多