Facebook流量不足

Facebook flux deficiency

在 flux-chat 示例中,MessageSection 侦听 ThreadStore 和 MessageStore,因此它在 ThreadStore 存储更改时呈现,并在 MessageStore 更改时再次呈现。但是,由于它的状态取决于两者,因此在状态未完成时完成第一次渲染。

除非我遗漏了什么,否则这不是很好,不是吗?

这只是一个示例,但该模式正在重复。

更新:经过长时间的讨论,这里是结论:

  1. React 确保 render 只在最后触发一次,即使 setState 被多次调用也是如此。
  2. 构建状态的 getter 函数将被多次调用,但由于这些是纯函数,它们不会导致错误,只会导致 'small' 开销。

我的建议是每个 React 组件最多使用一个存储,通过使用 waitFor 与它们协调从所有其他存储收集所有状态,然后在状态准备就绪时通知组件。这样就没有开销,也不依赖于 React 的内部魔法。这与 'View Model' 类似,但没有双向绑定,数据从存储到组件的单向流动。

一般情况下,这不是问题,只要每个店铺内部保持一致即可。如果商店之间存在数据依赖性,商店可以使用 waitFor 来确保数据以正确的顺序传播。

此外,即使 setState 被调用两次(每个更改事件一次),React 合成事件系统将多个 setState 调用分批处理到一个渲染中,这发生了 after 两个动作都被处理了。

为了证明这个案例,我对项目做了如下修改:

diff --git a/examples/flux-chat/js/components/MessageSection.react.js b/examples/flux-chat/js/components/MessageSection.react.js
index b803174..05bad0b 100644
--- a/examples/flux-chat/js/components/MessageSection.react.js
+++ b/examples/flux-chat/js/components/MessageSection.react.js
@@ -50,6 +50,7 @@ var MessageSection = React.createClass({
   },

   render: function() {
+    console.log("message section render");
     var messageListItems = this.state.messages.map(getMessageListItem);
     return (
       <div className="message-section">
diff --git a/examples/flux-chat/js/stores/MessageStore.js b/examples/flux-chat/js/stores/MessageStore.js
index 995ef39..3436a0f 100644
--- a/examples/flux-chat/js/stores/MessageStore.js
+++ b/examples/flux-chat/js/stores/MessageStore.js
@@ -94,6 +94,7 @@ var MessageStore = assign({}, EventEmitter.prototype, {
 });

 MessageStore.dispatchToken = ChatAppDispatcher.register(function(action) {
+  console.log("message store", action.type);

   switch(action.type) {

diff --git a/examples/flux-chat/js/stores/ThreadStore.js b/examples/flux-chat/js/stores/ThreadStore.js
index a73ceb3..e14f35d 100644
--- a/examples/flux-chat/js/stores/ThreadStore.js
+++ b/examples/flux-chat/js/stores/ThreadStore.js
@@ -103,6 +103,7 @@ var ThreadStore = assign({}, EventEmitter.prototype, {
 });

 ThreadStore.dispatchToken = ChatAppDispatcher.register(function(action) {
+  console.log("thread store", action.type);

   switch(action.type) {

在 JavaScript 控制台中,您可以看到 MessageSection 在两个操作都已处理之前不会重新呈现。

所以,在这种情况下,唯一的额外工作是 getStateFromStores 被调用两次而不是一次,但我相信一点点额外的开销是值得的,以利用简化的心智模型只需从任何需要更新的商店发出更改事件。

请记住,通量的黄金法则是:改变存储数据的唯一方法是通过操作。在商店中公开的函数应该 永远不会 改变数据——它们应该是纯函数。因此,多次调用它们不会导致错误。