setState原理

setSate接受两个参数,一个是state,另一个是回调函数

注意点:

  • 主要是通过队列机制实现state更新,当执行setState的时候,会将需要更新的state合并后放入状态队列中,而不会立即更新this.state。队列机制主要实现了批量更新state。
  • 如果我们不使用setState更新,而是直接采用this.state来修改,state不会被放入状态队列中,下次调用setState时对状态队列进行合并时,会忽略之前修改的state,就不会达到预期效果。
  • setState不保证是同步的,也可以认为是异步的,在setState之后,会对state进行diff,判断是否有改变,然后去diff是否要更新UI
    在这里插入图片描述
    内部实现:
    判断isBatchingUpdates是否为true,为true,则会把当前组件放入dirtyComponents 数组中,否则batchUpdate 所有队列中的更新
var batchingStrategy = {
  isBatchingUpdates: false,
  
  batchedUpdates: function(callback, a, b, c, d, e) {
    // ...
    batchingStrategy.isBatchingUpdates = true
    transaction.perform(callback, null, a, b, c, d, e); //事务
  }
};

事务流
transaction实际上做的事情就是将要执行的method使用wrapper封装起来,用提供的perform方法来调用method。在调用的过程中,会先顺序调用wrapper中注册的initialize方法,然后执行method方法,最后顺序调用wrapper中注册的close方法。initialize和close可以是调用transaction的模块自定义的。

例题

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

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

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

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

输出 0 0 2 3
两个调用栈
在这里插入图片描述

  • 两类调用栈相比,显然第1个调用栈更加复杂。在第1个调用栈中,发现调用setState前出现了close,perform,batchedUpdates等调用。原来在调用setState,执行流已经处于一个transaction中了。
  • 在往前分析,可以发现是_renderNewRootComponent方法调用了batchedUpdates,原来整个React Component的渲染过程就处在一个transaction中。
  • 这样就可以理解为什么第1次和第2次的setState执行后值没变了。因为在ComponentDidMount中调用setState时,渲染周期还没有结束,batchingStrategy中的isBatchingUpdates还是true,setState对应的components被存入dirtyComponents暂存起来,所以前2次setState之后的this.state.val的结果都是 0。
  • 再观察第2类调用栈,使用了setTimeout,会在结束当前调用栈之后执行,这时渲染周期已经结束,batchingStrategy中的isBatchingUpdates为false。setState会在执行流中调用,不会进入dirtyComponents存储,所以新的state会立马生效,打印第3次和第4次的this.state.val,就会出现生效后的值了。

借鉴文章1 | 文章2

  • 4
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值