// Renderers may schedule work to be done after host components are mounted // (eg DOM renderer may schedule auto-focus for inputs and form controls). // These effects should only be committed when components are first mounted, // aka when there is no current/alternate. if (current === null && flags & Update) { commitHostMount(finishedWork); }
functionflushSpawnedWork(): void { if ( pendingEffectsStatus !== PENDING_SPAWNED_WORK && // If a startViewTransition times out, we might flush this earlier than // after mutation phase. In that case, we just skip the after mutation phase. pendingEffectsStatus !== PENDING_AFTER_MUTATION_PHASE ) { return; } pendingEffectsStatus = NO_PENDING_EFFECTS;
const passiveSubtreeMask = PassiveMask; const rootDidHavePassiveEffects = // If this subtree rendered with profiling this commit, we need to visit it to log it. (finishedWork.subtreeFlags & passiveSubtreeMask) !== NoFlags || (finishedWork.flags & passiveSubtreeMask) !== NoFlags;
// Always call this before exiting `commitRoot`, to ensure that any // additional work on this root is scheduled. ensureRootIsScheduled(root);
// Read this again, since a passive effect might have updated it remainingLanes = root.pendingLanes;
// Check if this render scheduled a cascading synchronous update. This is a // heurstic to detect infinite update loops. We are intentionally excluding // hydration lanes in this check, because render triggered by selective // hydration is conceptually not an update. if ( (enableInfiniteRenderLoopDetection && (didIncludeRenderPhaseUpdate || didIncludeCommitPhaseUpdate)) || (includesSomeLane(lanes, UpdateLanes) && includesSomeLane(remainingLanes, SyncUpdateLanes)) ) { if (root === rootWithNestedUpdates) { nestedUpdateCount++; } else { nestedUpdateCount = 0; rootWithNestedUpdates = root; } } else { nestedUpdateCount = 0; }