14

我有这样的组件结构

<A>
    <B>
        <C/>
        <C/>
    </B>
    <D>
       <E/>
       <E/>
    </D>
</A>

想法是块 E 中组件上的操作由组件 A 的函数处理为 A 的状态,然后作为道具传递给 B 和 C。我知道,更好的方法是使用 Flux、pubsub-js 或其他 Store-message 系统,但希望有人能解释为什么按照我的理解正确的解决方案不起作用。

从组件 E 的多个实例中同时调用组件 A 的此函数会导致竞争条件只有一个状态更改(而不是每个函数调用都提供更改)

updateState(value,index){
   this.setState(update(this.state, {
        a: {
          [index]: {
            b: {
             $set: value
            }
          }
        }
    })
);
}

这里的函数更新来自

import update from 'react/lib/update';

与 ReactJS 推荐的做法背道而驰的糟糕解决方案,但效果很好:

updateState(value,index){
   this.state.a[index].b=value;
   this.forceUpdate();
);
}

我的问题是:

它是一个错误,多个同时 setState 调用竞争条件,还是我在不理解的情况下做错了什么?

4

2 回答 2

36

您可能想要传递一个setState应该删除此类竞争条件的函数。就像是:

this.setState(currentState => {
  currentState.someProp++;
  return currentState;
});

即使您的应用程序的两个不同部分同时执行此操作,这两个函数仍将被调用并someProp递增两次。

如果您改为这样做:this.setState({someProp: this.state.someProp + 1})它只会增加一次,因为this.state.someProp在调用setState. 但是当将一个函数传递给setState你时,你会得到当前的挂起状态作为参数,这让你可以选择像我的例子中那样增加,或者将你的突变与发生的任何其他突变合并。

于 2015-05-20T06:09:55.423 回答
7

根据 React 文档,如第一个答案中所述,您可以传递一个函数来确保原子性的操作。问题是您不应该修改状态,而是在传递的函数中返回新值:

setState(function(previousState, currentProps) {
  return {myInteger: previousState.myInteger + 1};
});

https://facebook.github.io/react/docs/component-api.html

于 2016-07-27T21:56:24.870 回答