ReactJS并发SetState竞争条件

aka*_*rog 7 race-condition setstate reactjs

我有这样的组件结构

<A>
    <B>
        <C/>
        <C/>
    </B>
    <D>
       <E/>
       <E/>
    </D>
</A>
Run Code Online (Sandbox Code Playgroud)

想法是对块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
            }
          }
        }
    })
);
}
Run Code Online (Sandbox Code Playgroud)

功能更新来自

import update from 'react/lib/update';
Run Code Online (Sandbox Code Playgroud)

反对ReactJS的错误解决方案推荐的做法,但效果很好:

updateState(value,index){
   this.state.a[index].b=value;
   this.forceUpdate();
);
}
Run Code Online (Sandbox Code Playgroud)

我的问题是:

这是一个错误,多个simalteneous setState调用竞争条件,或者我做错了什么而没有修改它?

And*_*ahl 19

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

this.setState(currentState => {
  currentState.someProp++;
  return currentState;
});
Run Code Online (Sandbox Code Playgroud)

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

如果你这样做:this.setState({someProp: this.state.someProp + 1})它只会增加一次,因为this.state.someProp在调用后不会直接更新setState.但是当setState你将一个函数传递给你时,你可以将当前的暂挂状态作为一个参数,这样你就可以选择像我的例子那样增加,或者将你的变异与发生的任何其他变异合并.

  • 您不应该更改传递给该函数的对象.您应该返回具有更改状态的新对象.并且该参数被称为`prevState`而不是`currentState`,它也暗示了这一点. (2认同)

小智 5

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

setState(function(previousState, currentProps) {
  return {myInteger: previousState.myInteger + 1};
});
Run Code Online (Sandbox Code Playgroud)

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