官网中说 react setState()方法 状态更新可能是异步的

官网详情移步:https://react.docschina.org/docs/state-and-lifecycle.html

React 可以将多个setState() 调用合并成一个调用来提高性能。

因为 this.props 和 this.state 可能是异步更新的,你不应该依靠它们的值来计算下一个状态。

// Wrong 此代码`可能`无法更新计数器:
this.setState({
  counter: this.state.counter + this.props.increment,
});
// Correct
this.setState((prevState, props) => ({
  counter: prevState.counter + props.increment
}));

React 中 setState 什么时候是同步的,什么时候是不同步的?

回答:

在React中,如果是

由React引发的事件处理(比如:onClick),调用setState不会同步更新this.state;

绕过React引发的事件处理(比如: addEventListener直接添加、setTimeout/setInterval 产生的异步调用),调用setState会同步更新this.state;

原因:

在React的setState的函数实现中,根据变量isBatchingUpdates判断是否立即更新this.state。值为false则立即更新。

在调用 由React引发的事件处理 之前,会调用batchedUpdates函数,将isBatchingUpdates的值修改为true,也就是不同步更新this.state。

观察下面代码的输出 (React setState)

class Example extends React.Component {
  constructor() {
    super();
    this.state = {
      val: 0
    };
  }
  
  componentDidMount() {
    this.setState({val: this.state.val + 1});
    console.log(this.state.val);    // 第 1 次 log ---- 0

    this.setState({val: this.state.val + 1});
    console.log(this.state.val);    // 第 2 次 log ---- 0

    setTimeout(() => {
      this.setState({val: this.state.val + 1});
      console.log(this.state.val);  // 第 3 次 log ---- 2

      this.setState({val: this.state.val + 1});
      console.log(this.state.val);  // 第 4 次 log ---- 3
    }, 0);
  }

  render() {
    return null;
  }
};
  1. 第 1 次 log, 第 2 次 log 都是在React自身的生命周期中,调用之前触发batchedUpdates函数,isBatchingUpdates为true,所以不会立即更新this.state,而是加入了脏组件

  2. 两次 setState 时,获取到 this.state.val 都是 0,所以执行时都是将 0 设置成 1,在 react 内部会被合并掉,只执行一次。设置完成后 state.val 值为 1。

  3. setTimeout时,isBatchingUpdates为false,所以会立即更新this.state。

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐