这是一个SSCCE。我们有一个简单的计数器,一个递增一次的按钮,以及一个连续三次递增的按钮:
由于setState
的异步性质,以下天真的实施不起作用:
const App = React.createClass({
getInitialState: function() {
return {counter: 0};
}
, incCounter() {
this.setState({counter: this.state.counter+1});
}
, incCounterInBurst() {
for (let i = 0; i < 3; i++)
this.incCounter();
}
, render: function() {
return (
<div>
<div>{this.state.counter}</div>
<div>
<button onClick={this.incCounter}>
inc
</button>
<button onClick={this.incCounterInBurst}>
inc X 3
</button>
</div>
</div>
);
}
});
export default App;
具体来说,如果您使用上述实现单击inc X 3
按钮,它将仅按1实现计数器。
我找到了两种方法来完成这项工作:
按照here所述,在(prevState, props)=>newState
中传递setState
个功能。唯一需要改变的是incCounter
方法:
, incCounter() {
this.setState((prevState, _)=>{return {counter: prevState.counter+1}});
}
我发现另一种方法在当前堆栈清除后强制setState
调用的序列化(缺少更好的单词)。此方法完全按照原始实现中的incCounter
方法保留,并更改incCounterInBurst
方法:
const TimerMixin = require('react-timer-mixin');
const App = React.createClass({
mixins: [TimerMixin],
...
, incCounter() { // same as in the initial, erroenous implementation
this.setState({counter: this.state.counter+1});
}
, incCounterInBurst() {
for (let i = 0; i < 3; i++)
this.setTimeout( ()=>{this.incCounter();}, 0);
}
...
}
我还没有看到method 2
在任何地方提到,但你认为它比method 1
提供了什么优势,还是有其他更高效/惯用的方法来处理这个问题?限制是我们显然需要incCounterInBurst
方法来利用现有的incCounter
方法,而不仅仅是改变状态本身。