setState批量更新

1,622 阅读1分钟

原文理解:juejin.cn/post/684490…

react版本:16.8.6

异步:手动开启批量更新的api:

unstable_batchedUpdates: batchedUpdates$1

function batchedUpdates$1(fn, a) {
  var previousIsBatchingUpdates = isBatchingUpdates;
  isBatchingUpdates = true;
  try {
    return fn(a);
  } finally {
    isBatchingUpdates = previousIsBatchingUpdates;
    if (!isBatchingUpdates && !isRendering) {
         performSyncWork();
    }
  }
}

是否批量更新是由变量isBatchingUpdates控制的。 在合成事件中:

function interactiveUpdates$1(fn, a, b) {
  // If there are any pending interactive updates, synchronously flush them.
  // This needs to happen before we read any handlers, because the effect of
  // the previous event may influence which handlers are called during
  // this event.
  if (!isBatchingUpdates && !isRendering && lowestPriorityPendingInteractiveExpirationTime !== NoWork) {
    // Synchronously flush pending interactive updates.
    performWork(lowestPriorityPendingInteractiveExpirationTime, false);
    lowestPriorityPendingInteractiveExpirationTime = NoWork;
  }
  var previousIsBatchingUpdates = isBatchingUpdates;
  isBatchingUpdates = true;
  try {
    return scheduler.unstable_runWithPriority(scheduler.unstable_UserBlockingPriority, function () {
      return fn(a, b);
    });
  } finally {
    isBatchingUpdates = previousIsBatchingUpdates;
    if (!isBatchingUpdates && !isRendering) {
      performSyncWork();
    }
  }
}

1:除了设置isBatchingUpdates为true以外,下面是一个try-finally代码块。这个fn函数调用,就是调用合成事件回调,然后finally中才调用批量更新performSyncWork。解决问题1:setstate为什么是异步的。

instance.componentDidMount();
commitUpdateQueue(finishedWork, updateQueue, instance, committedExpirationTime);

2:声明周期中同合成事件一样,先调用生命周期函数,再调用批量更新

同步

1:原生事件和setTimeout,Promise中的可以同步,同步的原因是事件循环机制 2:unstable_batchedUpdates()中可以实现同步

function batchedUpdates$1(fn, a) {
  var previousIsBatchingUpdates = isBatchingUpdates;
  isBatchingUpdates = true;
  try {
    return fn(a);
  } finally {
    isBatchingUpdates = previousIsBatchingUpdates;
    if (!isBatchingUpdates && !isRendering) {
      performSyncWork();
    }
  }
}

注意:

setState异步及批量更新是因为生命周期及合成事件通过try...finally进行了批量调用。但是setState本身并没有调用。批量更新。因此通过事件循环放在队列中,是可以同步进行的。