首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >react setstate接受对象在setInterval和onClick中是不同的

react setstate接受对象在setInterval和onClick中是不同的
EN

Stack Overflow用户
提问于 2017-12-02 03:51:36
回答 2查看 215关注 0票数 1

我对setState()接受的object.The代码链接感到困惑,这里是https://codepen.io/DRL9/pen/jadbWq,代码如下:

代码语言:javascript
运行
复制
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>;
}
}

我希望当我单击按钮时,1会像行为一样增加。然而,它增加了2每个滴答。唯一不同的是,一个更新是在setInterval函数中,另一个更新是在onClick函数中。

为什么他们的行为不同?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-12-02 04:54:58

我们不能以绝对的方式谈论setState的时间,从定义上来说,它就是setState状态更改可能会延迟到将来的某个时间,根据您正在使用的React版本,这种行为可能会有所不同。

在提供的示例中,React将状态更新推迟到onClick处理程序运行完毕。React知道这个处理程序什么时候完成运行,因为我们通过JSX的onClick传递处理程序(然后由are在内部处理):

代码语言:javascript
运行
复制
// React processes the onClick handler below
<button id="btn" onClick={this.onClick.bind(this)}>increment</button> 

如果我们自己来测试onClick逻辑,通过从DOM中手动抓取button元素并添加一个调用onClick处理程序的单击事件侦听器,button将相同地更新到setInterval (React不知道我们在单击处理程序中更新状态,因此它选择不优化对setState的批处理)。

请参见此码页,其中按钮计数器在componentDidMount函数中手动添加了一个单击处理程序,而不是使用JSX的onClick。注意,按钮计数器现在以间隔2而不是1递增。

我想强调的是,这种行为是,而不是确定性的,您不应该在setState函数中使用this.state。相反,您希望使用setState的变体,它接受包含前一个状态的更新器函数。然后,从传递给更新程序的状态构建新状态:

代码语言:javascript
运行
复制
this.setState(state => ({
    buttonCount: state.buttonCount + this.increment
}));

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

有关setState的更多信息,请参见正式文件

票数 2
EN

Stack Overflow用户

发布于 2017-12-02 04:19:49

来自setState文档

把setState()看作是一个请求,而不是更新组件的直接命令。为了更好地感知性能,React可能会延迟它,然后一次更新几个组件。React不能保证立即应用状态更改。

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

至于为什么intervalCount一直被立即更新(因此是第二次更新)和buttonCount一直被批处理(对setState的两个调用只增加一次),我的猜测是:onClick是由用户交互触发的,因此响应引擎可能猜测,在用户交互期间,许多状态可能会发生变化,因此它会对对setState的调用进行批处理,直到事件完全传播为止。另一方面,tick是由内部回调触发的,而不需要处理任何用户交互,因此,React引擎可能猜测无需批处理就立即更新状态是安全的。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/47604398

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档