Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/371.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript react setstate接受对象在setInterval和onClick中不同_Javascript_Reactjs - Fatal编程技术网

Javascript react setstate接受对象在setInterval和onClick中不同

Javascript react setstate接受对象在setInterval和onClick中不同,javascript,reactjs,Javascript,Reactjs,我对setState()接受的对象感到困惑。代码链接在这里,代码如下: class Counter extends React.Component { constructor(props) { super(props); this.state = { intervalCount: 1, buttonCount: 1 }; this.increment = 1; this.intervalId = null; } tick()

我对
setState()
接受的对象感到困惑。代码链接在这里,代码如下:

class Counter extends React.Component {
constructor(props) {
    super(props);
    this.state = {
        intervalCount: 1,
        buttonCount: 1
    };
    this.increment = 1;
    this.intervalId = null;
}
tick() {
    this.setState({
        intervalCount: this.state.intervalCount + this.increment
    });
    this.setState({
        intervalCount: this.state.intervalCount + this.increment
    });
}
onClick() {
    this.setState({
        buttonCount: this.state.buttonCount + this.increment
    });
    this.setState({
        buttonCount: this.state.buttonCount + this.increment
    });
}
componentDidMount() {
    this.intervalId = setInterval(() => this.tick(), 1000);
}
componentWillUnmount() {
    clearInterval(this.intervalId);
}
render() {
    return <div>
        <div>
            interval counter: {this.state.intervalCount}
        </div>
        <button onClick={this.onClick.bind(this)}>increment</button>
        <div>
            button counter: {this.state.buttonCount}
        </div>
    </div>;
}
}
类计数器扩展React.Component{
建造师(道具){
超级(道具);
此.state={
间隔时间:1,
按钮计数:1
};
这个增量=1;
this.intervalId=null;
}
勾选(){
这是我的国家({
intervalCount:this.state.intervalCount+this.increment
});
这是我的国家({
intervalCount:this.state.intervalCount+this.increment
});
}
onClick(){
这是我的国家({
buttonCount:this.state.buttonCount+this.increment
});
这是我的国家({
buttonCount:this.state.buttonCount+this.increment
});
}
componentDidMount(){
this.intervalId=setInterval(()=>this.tick(),1000);
}
组件将卸载(){
clearInterval(此为有效期);
}
render(){
返回
间隔计数器:{this.state.intervalCount}
增量
按钮计数器:{this.state.buttonCount}
;
}
}
我希望
intervalCount
会增加1,就像我单击增量按钮时的行为一样。但是,它会在每个刻度上增加2个。 唯一不同的是,一个在
setInterval
函数中更新,另一个在
onClick
函数中更新

为什么他们的行为不同?

与:

将setState()视为更新组件的请求,而不是即时命令。为了更好地感知性能,React可能会延迟它,然后在一次过程中更新多个组件。React不保证立即应用状态更改

这意味着,当您在使用
setState
更改状态数据后立即引用状态数据(
This.state.buttonCount
This.state.intervalCount
)时(就像您在第二个
setState
命令的两个函数中所做的那样),行为将是不可预测的。可能
setState
会立即更新状态数据,就像它在
intervalCount
中所做的那样,也可能
setState
会等待更新状态数据,以便它可以稍后对其进行批处理,就像它在
buttonCount
中所做的那样。作为一名开发人员,当我们想在同一事件中多次修改状态时,我们应该通过使用其他变量来避免暴露于这种不可预测的行为


至于为什么
intervalCount
会立即得到相当一致的更新(并因此第二次递增),而
buttonCount
会得到一致的批处理(并且对
setState
的两次调用只递增一次)我的猜测是:
onClick
是由用户交互触发的,因此React引擎可能会猜测在用户交互期间许多状态可能会发生变化,因此它会批量调用setState,可能直到事件完全传播<另一方面,代码>勾选,是由内部回调触发的,没有处理任何用户交互,因此React引擎可能会猜测在不进行批处理的情况下立即更新状态是安全的。

我们不能绝对谈论
设置状态
的时间,因为根据定义,不可预测。状态更改可能会延迟到将来的某个时间,并且此行为可能会有所不同,具体取决于您正在使用的React的版本

在提供的示例中,React延迟状态更新,直到
onClick
处理程序完成运行。React知道该处理程序何时完成运行,因为我们正在通过JSX的
onClick
(然后由React在内部处理)传递该处理程序:

请参阅此,它使用更新程序更新按钮计数器,以2的间隔更新按钮计数器,产生预期效果


有关
设置状态的更多信息,请参见

谢谢。我能理解你的猜测。你能提供证明你猜测的参考资料吗?我认为React团队不在乎指定规则,这样开发人员就不会依赖它了。无论如何,它可能比这更复杂-如果有多个组件、大量最近的用户交互等,可能会有所不同。对于“为什么它的行为不同”的问题,答案是“行为应该是不可预测的”。
// React processes the onClick handler below
<button id="btn" onClick={this.onClick.bind(this)}>increment</button> 
this.setState(state => ({
    buttonCount: state.buttonCount + this.increment
}));