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

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

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

然后通过快速 {{{reactMarkup}}呈现该标记,并通过{{{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() ,它不会有任何东西,因为我仍然不明白我将如何设置我的商店在服务器上的状态?

2015年2月5日更新

我仍然在寻找一个干净的解决scheme,不涉及使用Fluxible,Fluxxor,Reflux等第三方Flux实现。

2016年8月19日更新

使用Redux 。

如果您愿意使用alt.js,您可以使用alt.bootstrapalt.flush ( docs )

我使用节点js与反应服务器端渲染和alt.js作为我的通量实现。

这是它的样子:

 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) ); } 

看看调度器和雅虎的相关图书馆。

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

像fetchr和routr这样的雅虎库通过使用非常纯粹的dependency injectionforms(对于参数名称或类似的东西,没有parsing函数)来解决节点的这个限制。

相反,你可以在services / todo.js中定义像这样的函数:

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

在actions / createTodo.js中像这样的动作 :

 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会填充额外的参数
    • 然后它会调用你的callback
  • 在客户端:
    • fetchr客户端发出一个http请求
    • 服务器上的fetchr拦截它
    • 它使用正确的参数调用服务函数
    • 它将响应发送回客户端fetchr
    • 客户端fetchr处理调用您的callback

这只是冰山一angular。 这是一个非常复杂的模块组合,共同解决一个棘手的问题,并提供一个可用的api。 在现实世界的使用情况下,同构在本质上是复杂的。 这就是为什么许多通量实现不支持服务器端渲染的原因。

你也可能想看看不使用助焊剂。 对于所有的应用程序来说都没有意义,而且往往会阻碍它。 如果有的话,你通常只需要它的几个部分。 编程没有银子弹!

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

即使你不想使用Flummox,源代码也很容易理解,你可以使用它作为指导来自己动手:

https://github.com/acdlite/flummox

问题是,当你search“Flux服务器渲染” ,你立即碰到这个问题,没有提及由React.js社区 机架制作的Redux 。 您可以在Redux的文档中find很好的描述,为什么服务器渲染很重要,为什么我们需要将HTML内的初始状态发送到客户端(这是Flux变得不足的地方)以及如何这样做。