setState
我测试的 React 的版本为 16.13.0。
setState 同步异步是和执行上下文有关系,setState -> this.updater.enqueueSetState -> scheduleUpdateOnFiber,而函数 scheduleUpdateOnFiber 的关键逻辑如下,能看到什么时候同步和异步。
同步的条件:
- 第一个条件
LegacyUnbatchedContext 没有太明白
executionContext === NoContext,即无法获取执行上下文,比如 setTimeout、原生事件等;
- setState 同步更新,那么更新的时机是什么时候呢?
dispatchDiscreteEvent 之前会把队列中处理掉;
dispatchDiscreteEvent 之后,也会把队列处理掉;
- 其他还很多情况会调用
flushSyncCallbackQueue,大部分是 executionContext === NoContext 或者主动调用;
if (expirationTime === Sync) {
if ( // Check if we're inside unbatchedUpdates
(executionContext & LegacyUnbatchedContext) !== NoContext && // Check if we're not already rendering
(executionContext & (RenderContext | CommitContext)) === NoContext) {
// Register pending interactions on the root to avoid losing traced interaction data.
schedulePendingInteractions(root, expirationTime); // This is a legacy edge case. The initial mount of a ReactDOM.render-ed
// root inside of batchedUpdates should be synchronous, but layout updates
// should be deferred until the end of the batch.
performSyncWorkOnRoot(root);
} else {
ensureRootIsScheduled(root);
schedulePendingInteractions(root, expirationTime);
if (executionContext === NoContext) {
// Flush the synchronous work now, unless we're already working or inside
// a batch. This is intentionally inside scheduleUpdateOnFiber instead of
// scheduleCallbackForFiber to preserve the ability to schedule a callback
// without immediately flushing it. We only do this for user-initiated
// updates, to preserve historical behavior of legacy mode.
flushSyncCallbackQueue();
}
}
} else {
ensureRootIsScheduled(root);
schedulePendingInteractions(root, expirationTime);
}
// Only updates at user-blocking priority or greater are considered
if ((executionContext & DiscreteEventContext) !== NoContext && (
// discrete, even inside a discrete event.
priorityLevel === UserBlockingPriority$1 || priorityLevel === ImmediatePriority)) {
// This is the result of a discrete event. Track the lowest priority
// discrete update per root so we can flush them early, if needed.
if (rootsWithPendingDiscreteUpdates === null) {
rootsWithPendingDiscreteUpdates = new Map([[root, expirationTime]]);
} else {
var lastDiscreteTime = rootsWithPendingDiscreteUpdates.get(root);
if (lastDiscreteTime === undefined || lastDiscreteTime > expirationTime) {
rootsWithPendingDiscreteUpdates.set(root, expirationTime);
}
}
}
setState
我测试的
React的版本为16.13.0。setState同步异步是和执行上下文有关系,setState->this.updater.enqueueSetState->scheduleUpdateOnFiber,而函数scheduleUpdateOnFiber的关键逻辑如下,能看到什么时候同步和异步。同步的条件:
LegacyUnbatchedContext没有太明白executionContext === NoContext,即无法获取执行上下文,比如setTimeout、原生事件等;dispatchDiscreteEvent之前会把队列中处理掉;dispatchDiscreteEvent之后,也会把队列处理掉;flushSyncCallbackQueue,大部分是executionContext === NoContext或者主动调用;