美文网首页
setState 什么时候同步,什么时候异步?

setState 什么时候同步,什么时候异步?

作者: 欢欣的膜笛 | 来源:发表于2021-03-11 16:30 被阅读0次
    class Demo extends PureComponent {
      state={
        count: 0,
      }
      componentDidMount() {
        console.log('pre state', this.state.count); // pre state 0
        this.setState({
          count: this.state.count + 1
        });
        console.log('next state', this.state.count); // next state 0
    
        //测试setTimeout
        setTimeout(() => {
          console.log('setTimeout pre state', this.state.count); // setTimeout pre state 1
          this.setState({
            count: this.state.count + 1
          });
          console.log('setTimeout next state', this.state.count); // setTimeout next state 2
        }, 0);
      }
    
      onClick = (event) => {
        // 测试合成函数中setState
        console.log(`${event.type} pre state`, this.state.count); // click pre state 2
        this.setState({
          count: this.state.count + 1
        });
        console.log(`${event.type} next state`, this.state.count); // click next state 2
      }
    
      render() {
        return <button onClick={this.onClick}>count+1</button>
      }
    }
    

    这里有三种方法调用 setState:

    1. 在 componentDidMount 中直接调用 setState;
    2. 在 componentDidMount 的 setTimeout 方法里调用 setState;
    3. 在 dom 中绑定 onClick 直接调用 setState;

    在 React 中,如果是由 React 引发的事件处理(比如通过 onClick 引发的事件处理),调用 setState 不会同步更新 this.state,除此之外的 setState 调用会同步执行 this.state。所谓“除此之外”,指的是绕过 React 通过 addEventListener 直接添加的事件处理函数,还有通过 setTimeout / setInterval 产生的异步调用。
    原因:在 React 的 setState 函数实现中,会根据一个变量 isBatchingUpdates 判断是直接更新 this.state 还是放到队列中回头再说,而 isBatchingUpdates 默认是 false,也就表示 setState 会同步更新 this.state,但是,有一个函数 batchedUpdates,这个函数会把 isBatchingUpdates 修改为 true,而当 React 在调用事件处理函数之前就会调用这个 batchedUpdates,造成的后果,就是由 React 控制的事件处理过程 setState 不会同步更新 this.state。

    结论:

    1. setState 在生命周期函数和合成函数中都是异步更新。
    2. setState 在 setTimeout、原生事件和 async 函数中都是同步更新。每次更新不代表都会触发 render,如果 render 内容与 newState 有关联,则会触发,否则即便 setState 多次也不会 render。
    3. 如果 newState 内容与 render 有依赖关系,就不建议同步更新,因为每次 render 都会完整的执行一次批量更新流程(只是 dirtyComponets 长度为1,stateQueue 也只有该组件的 newState),调用一次 diff 算法,这样会影响 React 性能。
    4. 如果没有必须同步渲染的理由,不建议使用同步,会影响 react 渲染性能。

    相关文章

      网友评论

          本文标题:setState 什么时候同步,什么时候异步?

          本文链接:https://www.haomeiwen.com/subject/cbfoqltx.html