React setState 中的竞争条件
Race Condition in React setState
问题:
一个组件的多个子组件几乎同时触发了事件。这些事件中的每一个都由 handleChange
样式函数处理,这些函数使用 React 的不变性助手将复杂对象合并到控制组件的状态中,通过类似于;
this.setState(React.addons.update(this.state, {$merge: new_value_object}));
这在事件独立触发时工作正常,但当多个事件以这种方式导致状态更新时,每个事件都单独从状态的 old 版本合并。 IE。 (伪代码,不打算执行)。
function logState() { console.log(this.state) }
logState(); // {foo: '', bar: ''}
var next_value_object_A = {foo: '??'}
var next_value_object_B = {bar: '!!'}
this.setState(React.addons.update(this.state, {$merge: new_value_object_A}),
logState);
this.setState(React.addons.update(this.state, {$merge: new_value_object_B}),
logState);
会产生;
{foo: '??', bar: ''}
{foo: '', bar: '!!'}
我不想使用的糟糕解决方案:
以下似乎有效,但似乎也是一个主要反模式;
setSynchronousState: function(nextState){
this.state = React.addons.update(this.state, {$merge: nextState});
this.setState(this.state);
}
这依赖于直接修改State。我在 运行 这段代码中没有看到任何直接的问题,它确实解决了手头的问题,但我不得不想象我继承了这个解决方案的一些巨大的技术债务。
这个解决方案稍微好一点的版本是;
getInitialState: function(){
this._synchronous_state = //Something
return this._synchronous_state;
},
_synchronous_state: {},
setSynchronousState: function(nextState){
this._synchronous_state = React.addons.update(this._synchronous_state, {$merge: nextState});
this.setState(this._synchronous_state);
}
这成功地避免了直接接触 this.state
,尽管现在我们遇到了在应用程序周围传递信息冲突的问题。每个其他函数现在都需要知道它是在访问 this.state
还是 this._synchronous_state
.
问题:
有没有更好的办法解决这个问题?
回答我自己的问题以防其他人看到这个问题;
this.setState
可以接受函数作为参数,而不是对象,如下所示;
this.setState(function(state){
...
return newState
});
这允许您通过传递给该函数的参数访问当前状态(在执行时)。
问题:
一个组件的多个子组件几乎同时触发了事件。这些事件中的每一个都由 handleChange
样式函数处理,这些函数使用 React 的不变性助手将复杂对象合并到控制组件的状态中,通过类似于;
this.setState(React.addons.update(this.state, {$merge: new_value_object}));
这在事件独立触发时工作正常,但当多个事件以这种方式导致状态更新时,每个事件都单独从状态的 old 版本合并。 IE。 (伪代码,不打算执行)。
function logState() { console.log(this.state) }
logState(); // {foo: '', bar: ''}
var next_value_object_A = {foo: '??'}
var next_value_object_B = {bar: '!!'}
this.setState(React.addons.update(this.state, {$merge: new_value_object_A}),
logState);
this.setState(React.addons.update(this.state, {$merge: new_value_object_B}),
logState);
会产生;
{foo: '??', bar: ''}
{foo: '', bar: '!!'}
我不想使用的糟糕解决方案:
以下似乎有效,但似乎也是一个主要反模式;
setSynchronousState: function(nextState){
this.state = React.addons.update(this.state, {$merge: nextState});
this.setState(this.state);
}
这依赖于直接修改State。我在 运行 这段代码中没有看到任何直接的问题,它确实解决了手头的问题,但我不得不想象我继承了这个解决方案的一些巨大的技术债务。
这个解决方案稍微好一点的版本是;
getInitialState: function(){
this._synchronous_state = //Something
return this._synchronous_state;
},
_synchronous_state: {},
setSynchronousState: function(nextState){
this._synchronous_state = React.addons.update(this._synchronous_state, {$merge: nextState});
this.setState(this._synchronous_state);
}
这成功地避免了直接接触 this.state
,尽管现在我们遇到了在应用程序周围传递信息冲突的问题。每个其他函数现在都需要知道它是在访问 this.state
还是 this._synchronous_state
.
问题:
有没有更好的办法解决这个问题?
回答我自己的问题以防其他人看到这个问题;
this.setState
可以接受函数作为参数,而不是对象,如下所示;
this.setState(function(state){
...
return newState
});
这允许您通过传递给该函数的参数访问当前状态(在执行时)。