当前位置: 首页 > news >正文

React19源码阅读之commitRoot

commitRoot入口

在finishConcurrentRender函数,commitRootWhenReady函数,commitRoot函数。

commitRoot流程图

commitRoot函数

commitRoot 函数是 React 渲染流程中用于提交根节点的关键函数。它的主要作用是设置相关的优先级和状态,然后调用 commitRootImpl 函数来实际执行根节点的提交操作,最后在操作完成后恢复之前的状态。

函数参数含义

  1. root: 类型为 FiberRoot,代表 React 应用的根节点,包含了整个应用的渲染信息。
  2. recoverableErrors: 类型为 null | Array<CapturedValue<mixed>>,是一个可恢复错误的数组,用于处理在渲染过程中捕获到的可恢复错误。
  3. transitions: 类型为 Array<Transition> | null,表示渲染过程中涉及的过渡任务数组。
  4. didIncludeRenderPhaseUpdate: 布尔类型,指示渲染阶段是否包含更新操作。
  5. spawnedLane: 类型为 Lane,表示在渲染过程中产生的新的渲染优先级车道。
  6. updatedLanes: 类型为 Lanes,表示在渲染过程中更新的渲染优先级车道。
  7. suspendedRetryLanes: 类型为 Lanes,表示暂停后重试的渲染优先级车道。
  8. suspendedCommitReason: 类型为 SuspendedCommitReason,是一个仅用于性能分析的参数,指示提交操作被暂停的原因。
  9. completedRenderStartTime: 数值类型,是一个仅用于性能分析的参数,记录渲染开始的时间。
  10. completedRenderEndTime: 数值类型,是一个仅用于性能分析的参数,记录渲染结束的时间。
function commitRoot(root: FiberRoot,recoverableErrors: null | Array<CapturedValue<mixed>>,transitions: Array<Transition> | null,didIncludeRenderPhaseUpdate: boolean,spawnedLane: Lane,updatedLanes: Lanes,suspendedRetryLanes: Lanes,// suspendedCommitReason: SuspendedCommitReason, // Profiling-only// completedRenderStartTime: number, // Profiling-only// completedRenderEndTime: number, // Profiling-only
) {const prevTransition = ReactSharedInternals.T;const previousUpdateLanePriority = getCurrentUpdatePriority();try {// 设置新的更新优先级并清空过渡状态setCurrentUpdatePriority(DiscreteEventPriority);ReactSharedInternals.T = null;commitRootImpl(root,recoverableErrors,transitions,didIncludeRenderPhaseUpdate,previousUpdateLanePriority,spawnedLane,updatedLanes,suspendedRetryLanes,suspendedCommitReason,completedRenderStartTime,completedRenderEndTime,);} finally {// 恢复之前的状态ReactSharedInternals.T = prevTransition;setCurrentUpdatePriority(previousUpdateLanePriority);}
}

commitRootImpl函数

commitRootImpl 函数是 React 渲染流程中用于提交根节点的核心函数,它负责将渲染阶段生成的结果应用到实际的 DOM 上,并执行相关的副作用操作。

  1. 更新 DOM:将 Fiber 树的变化应用到真实的 DOM 上,完成视图的更新。
  2. 执行副作用:处理各种副作用,包括 useEffectuseLayoutEffect 等钩子函数的执行,以及生命周期方法的调用。
  3. 清理和重置状态:在提交完成后,清理和重置相关的状态,为下一次渲染做准备
function commitRootImpl(root: FiberRoot,recoverableErrors: null | Array<CapturedValue<mixed>>,transitions: Array<Transition> | null,didIncludeRenderPhaseUpdate: boolean,renderPriorityLevel: EventPriority,spawnedLane: Lane,updatedLanes: Lanes,suspendedRetryLanes: Lanes,// suspendedCommitReason: SuspendedCommitReason, // Profiling-only// completedRenderStartTime: number, // Profiling-only// completedRenderEndTime: number, // Profiling-only
) {// 循环调用 flushPassiveEffects 函数,直到没有待处理的被动副作用。// 被动副作用通常包括 useEffect 钩子函数的执行。do {flushPassiveEffects();} while (rootWithPendingPassiveEffects !== null);// 获取已完成的 Fiber 树(finishedWork)和已完成的优先级车道(lanes)。const finishedWork = root.finishedWork;const lanes = root.finishedLanes;// 如果没有已完成的 Fiber 树,则直接返回。if (finishedWork === null) {return null;} // 将 root.finishedWork 和 root.finishedLanes 重置。root.finishedWork = null;root.finishedLanes = NoLanes;// 重置根节点的回调节点、回调优先级和取消待提交的状态。root.callbackNode = null;root.callbackPriority = NoLane;root.cancelPendingCommit = null;// 合并 finishedWork 的车道和子车道,得到剩余的优先级车道let remainingLanes = mergeLanes(finishedWork.lanes, finishedWork.childLanes);// 获取在渲染阶段并发更新的车道。const concurrentlyUpdatedLanes = getConcurrentlyUpdatedLanes();// 合并车道remainingLanes = mergeLanes(remainingLanes, concurrentlyUpdatedLanes);// 将 didIncludeCommitPhaseUpdate 标志重置为 false,用于检测提交阶段是否有递归更新。didIncludeCommitPhaseUpdate = false;// 如果根节点和工作进度根节点一致,则重置相关状态。if (root === workInProgressRoot) {// We can reset these now that they are finished.workInProgressRoot = null;workInProgress = null;workInProgressRootRenderLanes = NoLanes;} // 检查子树是否有 BeforeMutation、Mutation、Layout 或 Passive 副作用。const subtreeHasEffects =(finishedWork.subtreeFlags &(BeforeMutationMask | MutationMask | LayoutMask | PassiveMask)) !==NoFlags;// 检查根节点是否有 BeforeMutation、Mutation、Layout 或 Passive 副作用。const rootHasEffect =(finishedWork.flags &(BeforeMutationMask | MutationMask | LayoutMask | PassiveMask)) !==NoFlags;if (subtreeHasEffects || rootHasEffect) {const prevTransition = ReactSharedInternals.T;ReactSharedInternals.T = null;const previousPriority = getCurrentUpdatePriority();setCurrentUpdatePriority(DiscreteEventPriority);const prevExecutionContext = executionContext;executionContext |= CommitContext;// Before Mutation 阶段const shouldFireAfterActiveInstanceBlur = commitBeforeMutationEffects(root,finishedWork,);// Mutation 阶段// 执行 commitMutationEffects 函数,将 Fiber 树的变化应用到真实的 DOM 上。commitMutationEffects(root, finishedWork, lanes);if (enableCreateEventHandleAPI) {if (shouldFireAfterActiveInstanceBlur) {afterActiveInstanceBlur();}}resetAfterCommit(root.containerInfo);root.current = finishedWork;// Layout 阶段// 执行 commitLayoutEffects 函数,调用 useLayoutEffect 钩子函数和相关的生命周期方法。commitLayoutEffects(finishedWork, root, lanes);// 请求浏览器进行绘制,更新视图。requestPaint();// 恢复上下文和优先级executionContext = prevExecutionContext;setCurrentUpdatePriority(previousPriority);ReactSharedInternals.T = prevTransition;} else {// No effects.root.current = finishedWork;}const rootDidHavePassiveEffects = rootDoesHavePassiveEffects;// 如果根节点有被动副作用,则将相关状态存储起来,等待后续处理;否则,释放根节点的缓存池。if (rootDoesHavePassiveEffects) {rootDoesHavePassiveEffects = false;rootWithPendingPassiveEffects = root;pendingPassiveEffectsLanes = lanes;} else {releaseRootPooledCache(root, remainingLanes);}// Read this again, since an effect might have updated it
// 获取根节点的待处理优先级车道,如果没有剩余工作,则清除已失败的错误边界。remainingLanes = root.pendingLanes;//处理剩余工作和调度if (remainingLanes === NoLanes) {legacyErrorBoundariesThatAlreadyFailed = null;}// 确保根节点被正确调度,以便处理后续的更新。ensureRootIsScheduled(root);// Read this again, since a passive effect might have updated itremainingLanes = root.pendingLanes;// 检测无限更新循环,检测是否存在无限更新循环,若存在则增加嵌套更新计数。if ((enableInfiniteRenderLoopDetection &&(didIncludeRenderPhaseUpdate || didIncludeCommitPhaseUpdate)) ||// Was the finished render the result of an update (not hydration)?(includesSomeLane(lanes, UpdateLanes) &&// Did it schedule a sync update?includesSomeLane(remainingLanes, SyncUpdateLanes))) {if (root === rootWithNestedUpdates) {nestedUpdateCount++;} else {nestedUpdateCount = 0;rootWithNestedUpdates = root;}} else {nestedUpdateCount = 0;}// If layout work was scheduled, flush it now.// 刷新同步工作flushSyncWorkOnAllRoots();return null;
}

当根节点或子节点存在BeforeMutation、Mutation、Layout 或 Passiv副作用时,会执行:

  1. commitBeforeMutationEffects,是 React 渲染流程中提交阶段的一部分,主要用于在进行 DOM 突变(如更新、插入、删除节点)之前执行一些必要的准备工作和副作用操作。该函数会处理焦点管理、标记需要执行的副作用,并返回一个布尔值,指示是否应该触发在活动实例失去焦点后执行的回调。
  2. commitMutationEffects,数是 React 渲染流程中提交阶段的关键部分,它主要负责执行 DOM 突变(如插入、更新、删除节点)相关的副作用操作。此函数会在 React 完成协调阶段(reconciliation)后,将计算出的 DOM 变更应用到实际的 DOM 树上。
  3. commitLayoutEffects,是 React 提交阶段(Commit Phase)中的一个关键函数,主要负责执行布局副作用(Layout Effects)。在 React 的渲染流程中,当协调阶段(Reconciliation Phase)完成后,会进入提交阶段,这个阶段会将协调阶段计算出的变更应用到实际的 DOM 上。布局副作用是在 DOM 更新后立即执行的副作用,通常用于获取 DOM 节点的布局信息,如元素的宽度、高度等。
  4. requestPaint,用于请求浏览器进行一次重绘操作。

flushPassiveEffects函数

flushPassiveEffects 函数主要用于处理 React 中的被动副作用(passive effects)。被动副作用通常是指在渲染完成后异步执行的副作用,例如 useEffect 钩子中的一些操作。该函数会检查是否存在待处理的被动副作用,如果存在,则调用 flushPassiveEffectsImpl 函数来实际执行这些副作用,并在执行前后进行状态的保存和恢复,确保操作的正确性和状态的一致性。

function flushPassiveEffects(wasDelayedCommit?: boolean): boolean {
// rootWithPendingPassiveEffects 是一个全局变量,用于存储存在待处理被动副作用的根节点。
//如果该变量不为 null,则表示存在待处理的被动副作用,继续执行后续操作。if (rootWithPendingPassiveEffects !== null) {// 获取存在待处理被动副作用的根节点。const root = rootWithPendingPassiveEffects;// 获取待处理被动副作用剩余的渲染优先级车道。const remainingLanes = pendingPassiveEffectsRemainingLanes;// 将待处理被动副作用剩余的渲染优先级车道重置为 NoLanes,表示已经开始处理这些副作用。pendingPassiveEffectsRemainingLanes = NoLanes;// lanesToEventPriority 函数将待处理被动副作用的渲染优先级车道转换为事件优先级。const renderPriority = lanesToEventPriority(pendingPassiveEffectsLanes);// 调用 lowerEventPriority 函数,取 DefaultEventPriority 和 renderPriority 中的较低优先级作为最终的执行优先级const priority = lowerEventPriority(DefaultEventPriority, renderPriority);const prevTransition = ReactSharedInternals.T;// 当前的更新优先级const previousPriority = getCurrentUpdatePriority();try {setCurrentUpdatePriority(priority);ReactSharedInternals.T = null;// 调用 flushPassiveEffectsImpl 函数实际执行被动副作用,并返回该函数的执行结果。return flushPassiveEffectsImpl(wasDelayedCommit);} finally {// 恢复之前的状态并释放根节点的缓存setCurrentUpdatePriority(previousPriority);ReactSharedInternals.T = prevTransition;// 释放根节点的缓存,传入根节点和剩余的渲染优先级车道作为参数。releaseRootPooledCache(root, remainingLanes);}}// 不存在待处理的被动副作用,直接返回 false。return false;
}

flushPassiveEffectsImpl

flushPassiveEffectsImpl 函数的主要作用是刷新待处理的被动副作用。被动副作用通常和 React 的 useEffect 钩子相关,在渲染完成后异步执行。此函数会处理组件卸载和挂载时的被动副作用,同时处理过渡回调和同步工作。

function flushPassiveEffectsImpl(wasDelayedCommit: void | boolean) {// 检查是否有待处理的被动副作用if (rootWithPendingPassiveEffects === null) {return false;}// Cache and clear the transitions flag// 缓存并清除过渡标志const transitions = pendingPassiveTransitions;pendingPassiveTransitions = null;// 获取根节点和车道信息并重置const root = rootWithPendingPassiveEffects;const lanes = pendingPassiveEffectsLanes;rootWithPendingPassiveEffects = null;pendingPassiveEffectsLanes = NoLanes;// 检查是否正在渲染if ((executionContext & (RenderContext | CommitContext)) !== NoContext) {throw new Error('Cannot flush passive effects while already rendering.');}// 记录开始时间并设置执行上下文let passiveEffectStartTime = 0;const prevExecutionContext = executionContext;executionContext |= CommitContext;// 执行被动卸载和挂载副作用commitPassiveUnmountEffects(root.current);commitPassiveMountEffects(root,root.current,lanes,transitions,pendingPassiveEffectsRenderEndTime,);// 恢复执行上下文executionContext = prevExecutionContext;// 刷新所有根节点的同步工作flushSyncWorkOnAllRoots();// 若启用了过渡跟踪功能,缓存当前的过渡回调、根节点过渡回调和结束时间。若这些值都不为 null,将当前的过渡回调和结束时间重置为 null,并在空闲调度优先级下调度 processTransitionCallbacks 函数来处理过渡回调。if (enableTransitionTracing) {const prevPendingTransitionCallbacks = currentPendingTransitionCallbacks;const prevRootTransitionCallbacks = root.transitionCallbacks;const prevEndTime = currentEndTime;if (prevPendingTransitionCallbacks !== null &&prevRootTransitionCallbacks !== null &&prevEndTime !== null) {currentPendingTransitionCallbacks = null;currentEndTime = null;scheduleCallback(IdleSchedulerPriority, () => {processTransitionCallbacks(prevPendingTransitionCallbacks,prevEndTime,prevRootTransitionCallbacks,);});}}return true;
}

commitPassiveUnmountEffects

function commitPassiveUnmountEffects(finishedWork: Fiber): void {// resetComponentEffectTimers();commitPassiveUnmountOnFiber(finishedWork);
}

commitPassiveUnmountOnFiber

commitPassiveUnmountOnFiber 函数的主要作用是在 React 渲染流程的提交阶段,对指定的 Fiber 节点执行被动卸载副作用的操作。被动卸载副作用通常与 useEffect 钩子的清理函数相关,当组件卸载时,这些清理函数会被调用。该函数会根据 Fiber 节点的不同类型,执行相应的卸载逻辑。

function commitPassiveUnmountOnFiber(finishedWork: Fiber): void {// const prevEffectStart = pushComponentEffectStart();switch (finishedWork.tag) {case FunctionComponent:case ForwardRef:case SimpleMemoComponent: {recursivelyTraversePassiveUnmountEffects(finishedWork);if (finishedWork.flags & Passive) {commitHookPassiveUnmountEffects(finishedWork,finishedWork.return,HookPassive | HookHasEffect,);}break;}case HostRoot: {// const prevEffectDuration = pushNestedEffectDurations();recursivelyTraversePassiveUnmountEffects(finishedWork);break;}case Profiler: {// const prevEffectDuration = pushNestedEffectDurations();recursivelyTraversePassiveUnmountEffects(finishedWork);break;}case OffscreenComponent: {const instance: OffscreenInstance = finishedWork.stateNode;const nextState: OffscreenState | null = finishedWork.memoizedState;const isHidden = nextState !== null;if (isHidden &&instance._visibility & OffscreenPassiveEffectsConnected &&(finishedWork.return === null ||finishedWork.return.tag !== SuspenseComponent)) {instance._visibility &= ~OffscreenPassiveEffectsConnected;recursivelyTraverseDisconnectPassiveEffects(finishedWork);} else {recursivelyTraversePassiveUnmountEffects(finishedWork);}break;}default: {recursivelyTraversePassiveUnmountEffects(finishedWork);break;}}// popComponentEffectStart(prevEffectStart);
}

recursivelyTraversePassiveUnmountEffects

递归遍历 Fiber 树,处理组件卸载时的被动副作用(如 useEffect 的清理函数)。它主要处理两类逻辑:

  1. 子节点删除:当父节点标记为需要删除子节点(ChildDeletion)时,遍历所有待删除的子节点,执行其被动卸载副作用。
  2. 子树被动副作用:遍历父节点的子树,对每个子节点调用 commitPassiveUnmountOnFiber,处理其被动卸载逻辑。
function recursivelyTraversePassiveUnmountEffects(parentFiber: Fiber): void {const deletions = parentFiber.deletions;// 如果父节点有子节点需要删除if ((parentFiber.flags & ChildDeletion) !== NoFlags) {if (deletions !== null) {for (let i = 0; i < deletions.length; i++) {const childToDelete = deletions[i];//当前要删除的子节点nextEffect = childToDelete;// 在子节点被删除前,执行其被动卸载副作用。commitPassiveUnmountEffectsInsideOfDeletedTree_begin(childToDelete,parentFiber,);}}// 断开已删除子节点的兄弟节点与旧 Fiber 树(alternate 指针)的连接,避免残留引用导致内存泄漏。detachAlternateSiblings(parentFiber);}// 遍历子树处理被动副作用if (parentFiber.subtreeFlags & PassiveMask) {let child = parentFiber.child;while (child !== null) {// 深度优先commitPassiveUnmountOnFiber(child);// 兄弟节点(广度优先)child = child.sibling;}}
}


commitPassiveUnmountEffectsInsideOfDeletedTree_begin

主要功能是在删除子树时,递归地执行该子树中所有 Fiber 节点的被动卸载副作用。它会遍历子树中的每个 Fiber 节点,对每个节点调用 commitPassiveUnmountInsideDeletedTreeOnFiber 函数来执行具体的卸载逻辑。

function commitPassiveUnmountEffectsInsideOfDeletedTree_begin(deletedSubtreeRoot: Fiber,nearestMountedAncestor: Fiber | null,
) {// 循环遍历 Fiber 节点while (nextEffect !== null) {const fiber = nextEffect;commitPassiveUnmountInsideDeletedTreeOnFiber(fiber, nearestMountedAncestor);// 处理子节点const child = fiber.child;if (child !== null) {child.return = fiber;nextEffect = child;} else {commitPassiveUnmountEffectsInsideOfDeletedTree_complete(deletedSubtreeRoot,);}}
}

commitPassiveUnmountEffectsInsideOfDeletedTree_complete

ommitPassiveUnmountEffectsInsideOfDeletedTree_complete 函数的主要功能是在删除子树的被动卸载副作用处理完成后,对删除子树中的 Fiber 节点进行清理工作,确保内存能够被正确释放,避免出现内存泄漏问题。它会遍历子树中的 Fiber 节点,逐个清理节点及其关联资源,并且在遍历过程中根据节点的兄弟节点和父节点信息进行路径回溯。

function commitPassiveUnmountEffectsInsideOfDeletedTree_complete(deletedSubtreeRoot: Fiber,
) {// 循环遍历 Fiber 节点while (nextEffect !== null) {const fiber = nextEffect;const sibling = fiber.sibling;const returnFiber = fiber.return;// 清理 Fiber 节点及其关联的资源,确保内存释放和旧节点引用断开。detachFiberAfterEffects(fiber);// 判断是否到达删除子树的根节点if (fiber === deletedSubtreeRoot) {nextEffect = null;return;}// 处理兄弟节点if (sibling !== null) {sibling.return = returnFiber;nextEffect = sibling;return;}// 回溯父节点nextEffect = returnFiber;}
}

commitPassiveUnmountInsideDeletedTreeOnFiber

function commitPassiveUnmountInsideDeletedTreeOnFiber(current: Fiber,nearestMountedAncestor: Fiber | null,
): void {switch (current.tag) {case FunctionComponent:case ForwardRef:case SimpleMemoComponent: {commitHookPassiveUnmountEffects(current,nearestMountedAncestor,HookPassive,);break;}case LegacyHiddenComponent:case OffscreenComponent: {if (enableCache) {if (current.memoizedState !== null &&current.memoizedState.cachePool !== null) {const cache: Cache = current.memoizedState.cachePool.pool;if (cache != null) {retainCache(cache);}}}break;}case SuspenseComponent: {if (enableTransitionTracing) {// We need to mark this fiber's parents as deletedconst offscreenFiber: Fiber = (current.child: any);const instance: OffscreenInstance = offscreenFiber.stateNode;const transitions = instance._transitions;if (transitions !== null) {const abortReason = {reason: 'suspense',name: current.memoizedProps.unstable_name || null,};if (current.memoizedState === null ||current.memoizedState.dehydrated === null) {abortParentMarkerTransitionsForDeletedFiber(offscreenFiber,abortReason,transitions,instance,true,);if (nearestMountedAncestor !== null) {abortParentMarkerTransitionsForDeletedFiber(nearestMountedAncestor,abortReason,transitions,instance,false,);}}}}break;}case CacheComponent: {if (enableCache) {const cache = current.memoizedState.cache;releaseCache(cache);}break;}case TracingMarkerComponent: {if (enableTransitionTracing) {// We need to mark this fiber's parents as deletedconst instance: TracingMarkerInstance = current.stateNode;const transitions = instance.transitions;if (transitions !== null) {const abortReason = {reason: 'marker',name: current.memoizedProps.name,};abortParentMarkerTransitionsForDeletedFiber(current,abortReason,transitions,null,true,);if (nearestMountedAncestor !== null) {abortParentMarkerTransitionsForDeletedFiber(nearestMountedAncestor,abortReason,transitions,null,false,);}}}break;}}
}

detachAlternateSiblings

detachAlternateSiblings 函数的主要作用是断开父 Fiber 节点旧版本(alternate)的子节点之间的兄弟关系。

当需要清理旧的 Fiber 节点时,该函数会将旧 Fiber 节点的子节点之间的兄弟引用断开,从而辅助垃圾回收机制更有效地回收这些不再使用的旧节点。

function detachAlternateSiblings(parentFiber: Fiber) {const previousFiber = parentFiber.alternate;if (previousFiber !== null) {// 检查旧版本父节点是否有子节点let detachedChild = previousFiber.child;if (detachedChild !== null) {// 开父节点与第一个子节点的连接。previousFiber.child = null;//  遍历并断开子节点的兄弟关系do {// 下一个子节点(兄弟节点)const detachedSibling = detachedChild.sibling;//断开其与兄弟节点的连接。detachedChild.sibling = null;detachedChild = detachedSibling;} while (detachedChild !== null);}}
}

commitPassiveUnmountOnFiber

commitPassiveUnmountOnFiber 函数的主要作用是在 React 渲染流程的提交阶段,对指定的 Fiber 节点执行被动卸载副作用的操作。被动卸载副作用通常与 useEffect 钩子的清理函数相关,当组件卸载时,这些清理函数会被调用。该函数会根据 Fiber 节点的不同类型,执行相应的卸载逻辑。

function commitPassiveUnmountOnFiber(finishedWork: Fiber): void {// const prevEffectStart = pushComponentEffectStart();switch (finishedWork.tag) {case FunctionComponent:case ForwardRef:case SimpleMemoComponent: {recursivelyTraversePassiveUnmountEffects(finishedWork);if (finishedWork.flags & Passive) {commitHookPassiveUnmountEffects(finishedWork,finishedWork.return,HookPassive | HookHasEffect,);}break;}case HostRoot: {// const prevEffectDuration = pushNestedEffectDurations();recursivelyTraversePassiveUnmountEffects(finishedWork);break;}case Profiler: {// const prevEffectDuration = pushNestedEffectDurations();recursivelyTraversePassiveUnmountEffects(finishedWork);break;}case OffscreenComponent: {const instance: OffscreenInstance = finishedWork.stateNode;const nextState: OffscreenState | null = finishedWork.memoizedState;const isHidden = nextState !== null;if (isHidden &&instance._visibility & OffscreenPassiveEffectsConnected &&(finishedWork.return === null ||finishedWork.return.tag !== SuspenseComponent)) {instance._visibility &= ~OffscreenPassiveEffectsConnected;recursivelyTraverseDisconnectPassiveEffects(finishedWork);} else {recursivelyTraversePassiveUnmountEffects(finishedWork);}break;}default: {recursivelyTraversePassiveUnmountEffects(finishedWork);break;}}// popComponentEffectStart(prevEffectStart);
}

commitHookPassiveUnmountEffects

function commitHookPassiveUnmountEffects(finishedWork: Fiber,nearestMountedAncestor: null | Fiber,hookFlags: HookFlags,
) {commitHookEffectListUnmount(hookFlags,finishedWork,nearestMountedAncestor,);
}

commitHookEffectListUnmount

commitHookEffectListUnmount 函数的主要功能是在 React 组件卸载时,对符合特定标志(flags)的副作用钩子(如 useEffectuseLayoutEffect 等)执行清理操作。在 React 中,副作用钩子可能会返回一个清理函数,用于在组件卸载时进行资源释放、取消订阅等操作,该函数就是负责调用这些清理函数的。

函数参数含义

  • flags: 类型为 HookFlags,是一个位掩码,用于筛选需要执行卸载操作的副作用钩子。不同的标志代表不同类型的副作用钩子,例如 Layout 标志可能对应 useLayoutEffectPassive 标志可能对应 useEffect
  • finishedWork: 类型为 Fiber,表示已经完成协调的 Fiber 节点,该节点包含了组件的副作用钩子信息。
  • nearestMountedAncestor: 类型为 Fiber | null,表示距离 finishedWork 最近的已挂载的祖先 Fiber 节点,在执行清理操作时可能会用到。
function commitHookEffectListUnmount(flags: HookFlags,finishedWork: Fiber,nearestMountedAncestor: Fiber | null,
) {try {// 获取副作用队列const updateQueue = finishedWork.updateQueue;// 获取最后一个const lastEffect = updateQueue !== null ? updateQueue.lastEffect : null;if (lastEffect !== null) {const firstEffect = lastEffect.next;let effect = firstEffect;do {// 检查当前副作用的 tag 是否与传入的 flags 匹配。如果匹配,说明该副作用需要执行卸载操作。if ((effect.tag & flags) === flags) {// Unmountconst inst = effect.inst;const destroy = inst.destroy;if (destroy !== undefined) {// 将 inst.destroy 设置为 undefined,表示清理函数已经执行过inst.destroy = undefined;// 调用 safelyCallDestroy 函数安全地执行清理函数safelyCallDestroy(finishedWork, nearestMountedAncestor, destroy);}}effect = effect.next;} while (effect !== firstEffect);}} catch (error) {// captureCommitPhaseError(finishedWork, finishedWork.return, error);}
}

flushSyncWorkOnAllRoots

function performSyncWorkOnRoot(root: FiberRoot, lanes: Lanes) {// This is the entry point for synchronous tasks that don't go// through Scheduler.const didFlushPassiveEffects = flushPassiveEffects();if (didFlushPassiveEffects) {return null;}const forceSync = true;performWorkOnRoot(root, lanes, forceSync);
}

工具函数之 detachFiberAfterEffects

detachFiberAfterEffects 函数的作用是在 React 组件卸载或更新完成后,清理 Fiber 节点及其关联的资源,确保内存释放和旧节点引用断开。它主要用于处理已完成副作用(如 DOM 更新、钩子回调)的 Fiber 节点,避免内存泄漏,并为后续的垃圾回收做准备。

function detachFiberAfterEffects(fiber: Fiber) {// 断开 alternate 引用并递归清理const alternate = fiber.alternate;if (alternate !== null) {fiber.alternate = null;detachFiberAfterEffects(alternate);}// 清空子节点和副作用相关属性fiber.child = null;fiber.deletions = null;fiber.sibling = null;// 处理宿主组件(如 DOM 节点)if (fiber.tag === HostComponent) {const hostInstance: Instance = fiber.stateNode;if (hostInstance !== null) {// 调用该函数清理 DOM 节点的关联资源(如事件监听器、自定义数据),确保 DOM 节点安全卸载。detachDeletedInstance(hostInstance);}}// 清空 stateNode(指向真实 DOM 节点的引用),避免内存泄漏。fiber.stateNode = null;// 重置 Fiber 节点状态fiber.return = null;fiber.dependencies = null;fiber.memoizedProps = null;fiber.memoizedState = null;fiber.pendingProps = null;fiber.stateNode = null;fiber.updateQueue = null;
}

工具函数之 detachDeletedInstance

function detachDeletedInstance(node: Instance): void {delete (node: any)[internalInstanceKey];delete (node: any)[internalPropsKey];delete (node: any)[internalEventHandlersKey];delete (node: any)[internalEventHandlerListenersKey];delete (node: any)[internalEventHandlesSetKey];
}

const randomKey = Math.random().toString(36).slice(2);
const internalInstanceKey = '__reactFiber$' + randomKey;
const internalPropsKey = '__reactProps$' + randomKey;
const internalContainerInstanceKey = '__reactContainer$' + randomKey;
const internalEventHandlersKey = '__reactEvents$' + randomKey;
const internalEventHandlerListenersKey = '__reactListeners$' + randomKey;
const internalEventHandlesSetKey = '__reactHandles$' + randomKey;
const internalRootNodeResourcesKey = '__reactResources$' + randomKey;
const internalHoistableMarker = '__reactMarker$' + randomKey;

工具函数之 lanesToEventPriority

lanesToEventPriority 函数的主要功能是将 React 的车道(Lanes)转换为对应的事件优先级(EventPriority)。在 React 的并发模式下,车道系统用于管理不同优先级的更新任务,而事件优先级则用于确定事件处理的紧急程度。该函数会根据传入的车道信息,找出最高优先级的车道,并将其映射为合适的事件优先级。

参数lanes:类型为 Lanes,表示一组车道。在 React 中,Lanes 是一种用于表示多个优先级车道的位掩码数据结构,每个车道代表一个不同的优先级。

function lanesToEventPriority(lanes: Lanes): EventPriority {// 获取最高优先级的车道const lane = getHighestPriorityLane(lanes);// 判断并返回离散事件优先级if (!isHigherEventPriority(DiscreteEventPriority, lane)) {return DiscreteEventPriority;}// 判断并返回连续事件优先级if (!isHigherEventPriority(ContinuousEventPriority, lane)) {return ContinuousEventPriority;}// 判断 lane 是否包含非空闲工作。if (includesNonIdleWork(lane)) {return DefaultEventPriority;}// 返回空闲事件优先级return IdleEventPriority;
}

// 表示没有事件优先级,它被映射到 NoLane。const NoEventPriority: EventPriority = NoLane;// 离散事件优先级,映射到 SyncLane。离散事件通常是指那些由用户交互触发的不连续事件,如点击、输入等。SyncLane 表示同步车道,这类事件的更新任务会被立即同步执行,以保证用户交互的即时响应。const DiscreteEventPriority: EventPriority = SyncLane;// 连续事件优先级,对应 InputContinuousLane。连续事件一般是指那些持续的用户交互事件,如滚动、拖动等。InputContinuousLane 用于处理这类连续事件的更新任务,确保在连续交互过程中页面的流畅性。const ContinuousEventPriority: EventPriority = InputContinuousLane;// 默认事件优先级,映射到 DefaultLane。当没有指定特定的事件优先级时,会使用默认优先级。DefaultLane 是一种通用的车道,用于处理大多数普通的更新任务。const DefaultEventPriority: EventPriority = DefaultLane;// 空闲事件优先级,对应 IdleLane。空闲事件是指那些在浏览器空闲时才会执行的任务,对实时性要求较低。IdleLane 中的任务会在浏览器有空闲资源时才会被执行,以避免影响其他高优先级任务的执行。const IdleEventPriority: EventPriority = IdleLane;

工具函数之 lowerEventPriority

lowerEventPriority 函数的主要功能是比较两个事件优先级(EventPriority),并返回其中较低的优先级。在 React 的协调和调度机制中,事件优先级用于决定不同任务的执行顺序,确保高优先级的任务能够优先得到处理。

函数参数含义

  • a:类型为 EventPriority,代表第一个需要比较的事件优先级。
  • b:类型为 EventPriority,代表第二个需要比较的事件优先级。

使用三元运算符进行条件判断,具体逻辑如下:

  • a === 0:如果 a 的值为 0,在 React 的优先级体系中,0 可能代表一种特殊的优先级(如最高优先级或者无优先级的特殊情况),此时直接返回 a
  • a > b:如果 a 的值大于 b,根据 React 中事件优先级的定义,值越大优先级越低,所以返回 a
  • 其他情况:如果上述两个条件都不满足,即 a 不为 0 且 a 小于等于 b,则返回 b
function lowerEventPriority(a: EventPriority,b: EventPriority,
): EventPriority {return a === 0 || a > b ? a : b;
}

工具函数之 mergeLanes

mergeLanes 函数的主要功能是合并两个车道(Lanes 或单个 Lane)。在 React 的调度系统里,车道(Lanes)机制用于对不同更新任务的优先级进行管理和区分。该函数借助按位或运算符 | 把两个车道合并成一个新的车道,从而将多个更新任务的优先级信息整合起来。

 function mergeLanes(a: Lanes | Lane, b: Lanes | Lane): Lanes {return a | b;
}const LaneA = 0b0001; // 二进制表示,代表第 1 个车道
const LaneB = 0b0010; // 二进制表示,代表第 2 个车道const mergedLanes = mergeLanes(LaneA, LaneB);
console.log(mergedLanes.toString(2)); // 输出: 0b0011,代表第 1 个和第 2 个车道的合并

工具函数之 getCurrentUpdatePriority

function getCurrentUpdatePriority(): EventPriority {return currentUpdatePriority;
}

工具函数之 setCurrentUpdatePriority

let currentUpdatePriority: EventPriority = NoEventPriority;function setCurrentUpdatePriority(newPriority: EventPriority): void {currentUpdatePriority = newPriority;
}

工具函数之 safelyCallDestroy

 function safelyCallDestroy(current: Fiber,// 已完成的fibernearestMountedAncestor: Fiber | null,destroy: () => void,
) {try {// 执行清理回调函数destroy();} catch (error) {// captureCommitPhaseError(current, nearestMountedAncestor, error);}
}

工具函数之 detachDeletedInstance

清除实例上的某些属性。调用该函数清理 DOM 节点的关联资源(如事件监听器、自定义数据),确保 DOM 节点安全卸载。

function detachDeletedInstance(node: Instance): void {delete (node: any)[internalInstanceKey];delete (node: any)[internalPropsKey];delete (node: any)[internalEventHandlersKey];delete (node: any)[internalEventHandlerListenersKey];delete (node: any)[internalEventHandlesSetKey];
}

const randomKey = Math.random().toString(36).slice(2);
const internalInstanceKey = '__reactFiber$' + randomKey;
const internalPropsKey = '__reactProps$' + randomKey;
const internalContainerInstanceKey = '__reactContainer$' + randomKey;
const internalEventHandlersKey = '__reactEvents$' + randomKey;
const internalEventHandlerListenersKey = '__reactListeners$' + randomKey;
const internalEventHandlesSetKey = '__reactHandles$' + randomKey;
const internalRootNodeResourcesKey = '__reactResources$' + randomKey;
const internalHoistableMarker = '__reactMarker$' + randomKey;

全局变量之事件优先级

// 表示没有优先级(初始状态或无效状态)。
export const NoEventPriority: EventPriority = NoLane;
// 离散事件优先级,最高优先级。用于需要立即同步执行的操作,如用户交互(点击、键盘事件)、setState 同步更新。这类操作会打断其他低优先级任务,立即执行。
export const DiscreteEventPriority: EventPriority = SyncLane;
// 连续事件优先级,用于连续触发的事件(如鼠标移动、滚动)。这类操作允许中断低优先级任务,但可以与其他连续任务合并,避免过度渲染。
export const ContinuousEventPriority: EventPriority = InputContinuousLane;
// 默认优先级,用于普通的状态更新(如异步数据加载完成后的更新)。任务会在离散和连续事件之后执行,但比空闲任务优先。
export const DefaultEventPriority: EventPriority = DefaultLane;
// 空闲优先级,最低优先级。用于非紧急任务(如性能优化、统计上报),仅在浏览器空闲时执行,可能被高优先级任务中断或丢弃。
export const IdleEventPriority: EventPriority = IdleLane;

const TotalLanes = 31;const NoLanes: Lanes = /*                 */ 0b0000000000000000000000000000000;
const NoLane: Lane = /*                   */ 0b0000000000000000000000000000000;const SyncHydrationLane: Lane = /*        */ 0b0000000000000000000000000000001;
const SyncLane: Lane = /*                 */ 0b0000000000000000000000000000010;
const SyncLaneIndex: number = 1;
const InputContinuousHydrationLane:Lane= /**/0b0000000000000000000000000000100;
const InputContinuousLane: Lane = /*      */ 0b0000000000000000000000000001000;const DefaultHydrationLane: Lane = /*     */ 0b0000000000000000000000000010000;
const DefaultLane: Lane = /*              */ 0b0000000000000000000000000100000;const SyncUpdateLanes: Lane = SyncLane | InputContinuousLane | DefaultLane;

相关文章:

  • 架构-系统工程与信息系统基础
  • 提升内容创作效率:AI原创文章批量生成工具优势
  • CentOS 7.9升级OpenSSH到9.9p2
  • 专家系统的一般结构解析——基于《人工智能原理与方法》的深度拓展
  • DRF凭什么更高效?Django原生API与DRF框架开发对比解析
  • 要从给定的数据结构中提取所有的 itemList 并将其放入一个新的数组中
  • 计算机视觉——速度与精度的完美结合的实时目标检测算法RF-DETR详解
  • Electron Forge【实战】百度智能云千帆大模型 —— AI聊天
  • VMware与Docker:虚拟化技术的双轨演进与融合实践
  • Nginx 反向代理,啥是“反向代理“啊,为啥叫“反向“代理?而不叫“正向”代理?它能干哈?
  • 第十四届蓝桥杯省B.砍树
  • 12.桥接模式:思考与解读
  • 2025年计算机视觉与智能通信国际会议(ICCVIC 2025)
  • 对话模型和补全模型区别
  • LabVIEW实现Voronoi图绘制功能
  • 使用Next.js构建单页面React应用
  • 再来1章linux 系列-11 系统的延迟任务及定时任务 at ,crontab,mail;/etc/at.allow,/etc/at.deny
  • 卷积神经网络(二)
  • 济南国网数字化培训班学习笔记-第二组-1节-输电线路工程
  • 数字隔离器,筑牢AC-DC数字电源中的“安全防线”
  • 大家聊中国式现代化|郑崇选:提升文化软实力,打造文化自信自强的上海样本
  • 限制再放宽!新版市场准入负面清单缩减到106项
  • 神二十明日发射,长二F火箭推进剂加注工作已完成
  • 蚌埠一动物园用染色犬扮熊猫引争议,园方回应:被投诉已撤走
  • 中方警告韩国公司不要向美军工企业出口含中国稀土矿物产品?外交部回应
  • 神舟二十号任务完成最后一次全区合练,发射场做好发射前各项准备