深入研究React中setState源码(5)

this.state的更新会在_processPendingState执行完执行。所以两次setState取到的都是this.state.count最初的值0,这就解释了之前的现象。其实,这也是React为了解决这种前后state依赖但是state又没及时更新的一种方案,因此在使用时大家要根据实际情况来判断该用哪种方式传参。来看个小例子直观感受下

handleClickOnLikeButton () {
  this.setState({ count: 0 }) // => this.state.count 还是 undefined
  this.setState({ count: this.state.count + 1}) // => undefined + 1 = NaN
  this.setState({ count: this.state.count + 2}) // => NaN + 2 = NaN
 }
//....VS ....
handleClickOnLikeButton () {
  this.setState((prevState) => {
   return { count: 0 }
  })
  this.setState((prevState) => {
   return { count: prevState.count + 1 } // 上一个 setState 的返回是 count 为 0,当前返回 1
  })
  this.setState((prevState) => {
   return { count: prevState.count + 2 } // 上一个 setState 的返回是 count 为 1,当前返回 3
  })
  // 最后的结果是 this.state.count 为 3
 }
...

setState流程还是很复杂的,设计也很精巧,避免了重复无谓的刷新组件。它的主要流程如下

  1. enqueueSetState将state放入队列中,并调用enqueueUpdate处理要更新的Component
  2. 如果组件当前正处于update事务中,则先将Component存入dirtyComponent中。否则调用batchedUpdates处理。
  3. batchedUpdates发起一次transaction.perform()事务
  4. 开始执行事务初始化,运行,结束三个阶段
    1. 初始化:事务初始化阶段没有注册方法,故无方法要执行
    2. 运行:执行setSate时传入的callback方法,一般不会传callback参数
    3. 结束:更新isBatchingUpdates为false,并执行FLUSH_BATCHED_UPDATES这个wrapper中的close方法
  5. FLUSH_BATCHED_UPDATES在close阶段,会循环遍历所有的dirtyComponents,调用updateComponent刷新组件,并执行它的pendingCallbacks, 也就是setState中设置的callback。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持黑区网络。