首页 文章

React Flux和服务器端渲染? (同构反应磁通)

提问于
浏览
41

使用同构应用程序设置应用程序的初始状态的一般做法是什么?没有Flux我会简单地使用类似的东西:

var props = { }; // initial state
var html = React.renderToString(MyComponent(props);

然后通过express-handlebars渲染该标记并通过 {{{reactMarkup}} 显示 .

在客户端设置初始状态我会做这样的事情:

if (typeof window !== 'undefined') {
    var props = JSON.parse(document.getElementById('props').innerHTML);
    React.render(MyComponent(props), document.getElementById('reactMarkup'));
}

所以基本上你是在服务器和客户端上设置状态两次,但是React会比较这些差异,在大多数情况下,它不会通过重新渲染来影响性能 .


当您在Flux架构中拥有操作和存储时,此原则将如何工作?在我的组件里面我可以做到:

getInitialState: function() {
  return AppStore.getAppState();
}

但是现在如何在服务器中设置 AppStore 的初始状态?如果我使用没有传递属性的 React.renderToString 它将调用 AppStore.getAppState() ,它赢得't have anything in it because I still don' t了解如何在服务器上的商店中设置状态?

2015年2月5日更新

我仍在寻找一种干净的解决方案,不涉及使用Fluxible,Fluxxor,Reflux等第三方Flux实施 .

2016年8月19日更新

使用Redux .

4 回答

  • 14

    如果您愿意使用alt.js,您可以使用 alt.bootstrapalt.flushdocs)来实现它

    我正在使用带有反应服务器端渲染的节点js和alt.js作为我的flux实现 .

    这是它的样子:

    var data = {}; // Get the data whatever you want and return it bootstrap ready.
    
    // Reminder - renderToString is synchronised
    var app = React.renderToString(
         AppFactory(data)
    );
    
    // In this point the react rendering was finished so we can flush the data and reset the stores
    
    alt.flush();
    

    在我的app.jsx中

    /**
     *
     */
    componentWillMount: function () {
    
        // This beauty here is that componentWillMount is run on the server and the client so this is all we need to do. No need for other third-party isomorphic frameworks
    
        alt.bootstrap(
            JSON.stringify(this.props, null, 3)
        );
    
    }
    
  • 0

    看看dispatchr和雅虎的相关库 .

    大多数flux实现在node.js中不起作用,因为它们使用单例存储,调度程序和操作,并且没有“我们已完成”的概念,这需要知道何时呈现到html并响应请求 .

    像fetchr和routr这样的Yahoo库通过使用非常纯粹的依赖注入形式来解决节点的这种限制(对于参数名称没有解析函数或类似的东西) .

    而是在_1186833中定义这样的api函数:

    create: function (req, resource, params, body, config, callback) {
    

    在_1186835中这样的行为:

    module.exports = function (context, payload, done) {
        var todoStore = context.getStore(TodoStore);
    ...
    context.dispatch('CREATE_TODO_START', newTodo);
    ...
    context.service.create('todo', newTodo, {}, function (err, todo) {
    

    最后一行间接调用services / todo.js中的create函数 . 在这种情况下,间接可以表示:

    • 在服务器上:
      当你在服务器上时,

    • fetchr会填充额外的参数

    • 然后调用你的回调

    • 在客户端:

    • fetchr客户端发出http请求
      服务器上的

    • fetchr拦截它

    • 它使用正确的参数调用服务函数

    • 它将响应发送回客户端fetchr

    • 客户端fetchr处理调用你的回调

    这只是冰山一角 . 这是一组非常复杂的模块,它们协同工作以解决棘手的问题并提供可用的API . 在现实世界的用例中,同构性本质上是复杂的 . 这就是为什么许多flux实现不支持服务器端渲染的原因 .

    您可能还想研究不使用flux . 它对所有应用程序都没有意义,而且往往只是妨碍了 . 大多数情况下,如果有的话,你只需要它的几个部分 . 编程中没有银子弹!

  • 1

    FakeRainBrigand是正确的,服务器端Flux的最大问题是单例 . Flummox通过不使用单例来解决这个问题,并使您能够将整个Flux设置封装到一个可重用的类中 . 然后,您只需在每个请求上创建一个新实例 . 结合React Router等路由解决方案,您可以制作完全同构的应用程序 .

    即使您不想使用Flummox,也很容易理解源代码,您可以将其用作指导自己鞭打的东西:

    https://github.com/acdlite/flummox

  • 3

    问题是,当你搜索"Flux server rendering"时,你会立即碰到这个问题而且没有提到Redux,由React.js社区rackt制作 . 您可以在Redux的documentation上找到很好的描述为什么服务器渲染很重要,为什么我们需要将 HTML 中的初始状态发送到客户端(这是Flux变得不足的地方)以及如何执行此操作 .

相关问题