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.bootstrap
和alt.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,源代码也很容易理解,你可以使用它作为指导来自己动手:
问题是,当你search“Flux服务器渲染” ,你立即碰到这个问题,没有提及由React.js社区 机架制作的Redux 。 您可以在Redux的文档中find很好的描述,为什么服务器渲染很重要,为什么我们需要将HTML
内的初始状态发送到客户端(这是Flux变得不足的地方)以及如何这样做。