node.js - 异步初始化 React.js 组件的服务器端渲染策略

标签 node.js reactjs flux reactjs-flux

的最大优势之一React.js 应该是 服务器端渲染 .问题是关键函数React.renderComponentToString()是同步的,这使得无法加载任何异步数据,因为组件层次结构是在服务器上呈现的。

假设我有一个用于评论的通用组件,我可以将其放置在页面上的几乎任何位置。它只有一个属性,某种标识符(例如放置评论的文章的 id),其他所有内容都由组件本身处理(加载、添加、管理评论)。

我真的很喜欢助焊剂 架构因为它让很多事情变得更容易,而且它的存储非常适合在服务器和客户端之间共享状态。一旦我的包含评论的商店被初始化,我就可以将它序列化并将它从服务器发送到客户端,在那里它很容易恢复。

问题是填充我的商店的最佳方式是什么。在过去的几天里,我一直在谷歌上搜索很多,我遇到了一些策略,考虑到 React 的这个特性被“推广”了多少,这些策略似乎都不是很好。

  • 在我看来,最简单的方法是在实际渲染开始之前填充我的所有商店。这意味着组件层次结构之外的某个地方(例如连接到我的路由器)。这种方法的问题是我几乎必须两次定义页面结构。考虑一个更复杂的页面,例如一个包含许多不同组件(实际博客文章、评论、相关文章、最新文章、推特流...)的博客页面。我必须使用 React 组件设计页面结构,然后在其他地方我必须定义填充当前页面的每个必需商店的过程。这对我来说似乎不是一个很好的解决方案。不幸的是,大多数同构教程都是这样设计的(例如这个很棒的 flux-tutorial)。
  • React-async .这种方法是完美的。它让我可以简单地在每个组件中的一个特殊函数中定义如何初始化状态(无论是同步还是异步),并且在将层次结构呈现为 HTML 时调用这些函数。它的工作方式是在状态完全初始化之前不会呈现组件。问题是它需要Fibers据我所知,这是一个改变标准 JavaScript 行为的 Node.js 扩展。虽然我真的很喜欢这个结果,但在我看来,我们并没有找到解决方案,而是改变了游戏规则。我认为我们不应该被迫这样做来使用 React.js 的这个核心功能。我也不确定这个解决方案的普遍支持。是否可以在标准 Node.js 虚拟主机上使用 Fiber?
  • 我自己想了想。我还没有真正考虑过实现细节,但总体思路是我会以类似于 React-async 的方式扩展组件,然后我会在根组件上重复调用 React.renderComponentToString()。在每次传递期间,我会收集扩展回调,然后在传递的 和 调用它们以填充商店。我将重复此步骤,直到填充当前组件层次结构所需的所有存储。有很多事情需要解决,我特别不确定性能。

  • 我错过了什么吗?还有另一种方法/解决方案吗?现在我正在考虑采用 react-async/fibers 方式,但我并不完全确定,如第二点所述。

    Related discussion on GitHub .显然,没有官方的方法,甚至没有解决方案。也许真正的问题是如何使用 React 组件。喜欢简单的 View 层(几乎是我的建议第一)还是喜欢真正的独立和独立组件?

    最佳答案

    如果您使用 react-router ,你可以定义一个 willTransitionTo组件中的方法,通过 Transition您可以调用的对象 .wait上。

    renderToString 是否同步并不重要,因为回调到 Router.run直到所有 .wait 才会被调用ed promise 已解决,所以到时候 renderToString在您可以填充商店的中间件中调用。即使商店是单例,您也可以在同步渲染调用之前临时设置它们的数据,组件会看到它。

    中间件示例:

    var Router = require('react-router');
    var React = require("react");
    var url = require("fast-url-parser");
    
    module.exports = function(routes) {
        return function(req, res, next) {
            var path = url.parse(req.url).pathname;
            if (/^\/?api/i.test(path)) {
                return next();
            }
            Router.run(routes, path, function(Handler, state) {
                var markup = React.renderToString(<Handler routerState={state} />);
                var locals = {markup: markup};
                res.render("layouts/main", locals);
            });
        };
    };
    
    routes对象(描述路由层次结构)与客户端和服务器逐字共享

    关于node.js - 异步初始化 React.js 组件的服务器端渲染策略,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25983001/

    相关文章:

    reactjs - 使用 react 钩子(Hook)过滤数据

    javascript - 终极版 : Accessing current state - best practice?

    json - 如何在 Flux 应用程序中处理嵌套 API 响应?

    node.js - 如何使用命令行安装kendo grid

    javascript - Node.JS - 文件名不接受变量

    javascript - 在客户端和nodejs服务器上使用静态javascript文件

    javascript - React子组件重新渲染而不改变状态

    node.js - Geddy - 创建新项目

    javascript - React 语义 UI 组件无法正确呈现

    javascript - setState 在react-bootstrap 模式中不起作用