在快速连续调用`setState`

时间:2016-12-22 17:17:01

标签: reactjs

这是一个SSCCE。我们有一个简单的计数器,一个递增一次的按钮,以及一个连续三次递增的按钮:

enter image description here

由于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实现计数器。

我找到了两种方法来完成这项工作:

方法1

按照here所述,在(prevState, props)=>newState中传递setState个功能。唯一需要改变的是incCounter方法:

, incCounter() {
    this.setState((prevState, _)=>{return {counter: prevState.counter+1}});
}

方法2

我发现另一种方法在当前堆栈清除后强制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方法,而不仅仅是改变状态本身。

0 个答案:

没有答案