React19源码阅读之commitRoot
commitRoot入口
在finishConcurrentRender函数,commitRootWhenReady函数,commitRoot函数。
commitRoot流程图

commitRoot函数
commitRoot 函数是 React 渲染流程中用于提交根节点的关键函数。它的主要作用是设置相关的优先级和状态,然后调用 commitRootImpl 函数来实际执行根节点的提交操作,最后在操作完成后恢复之前的状态。
函数参数含义
- root: 类型为 FiberRoot,代表 React 应用的根节点,包含了整个应用的渲染信息。
- recoverableErrors: 类型为 null | Array<CapturedValue<mixed>>,是一个可恢复错误的数组,用于处理在渲染过程中捕获到的可恢复错误。
- transitions: 类型为 Array<Transition> | null,表示渲染过程中涉及的过渡任务数组。
- didIncludeRenderPhaseUpdate: 布尔类型,指示渲染阶段是否包含更新操作。
- spawnedLane: 类型为 Lane,表示在渲染过程中产生的新的渲染优先级车道。
- updatedLanes: 类型为 Lanes,表示在渲染过程中更新的渲染优先级车道。
- suspendedRetryLanes: 类型为 Lanes,表示暂停后重试的渲染优先级车道。
- suspendedCommitReason: 类型为 SuspendedCommitReason,是一个仅用于性能分析的参数,指示提交操作被暂停的原因。
- completedRenderStartTime: 数值类型,是一个仅用于性能分析的参数,记录渲染开始的时间。
- 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 上,并执行相关的副作用操作。
- 更新 DOM:将
Fiber树的变化应用到真实的 DOM 上,完成视图的更新。 - 执行副作用:处理各种副作用,包括
useEffect、useLayoutEffect等钩子函数的执行,以及生命周期方法的调用。 - 清理和重置状态:在提交完成后,清理和重置相关的状态,为下一次渲染做准备
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副作用时,会执行:
- commitBeforeMutationEffects,是 React 渲染流程中提交阶段的一部分,主要用于在进行 DOM 突变(如更新、插入、删除节点)之前执行一些必要的准备工作和副作用操作。该函数会处理焦点管理、标记需要执行的副作用,并返回一个布尔值,指示是否应该触发在活动实例失去焦点后执行的回调。
- commitMutationEffects,数是 React 渲染流程中提交阶段的关键部分,它主要负责执行 DOM 突变(如插入、更新、删除节点)相关的副作用操作。此函数会在 React 完成协调阶段(reconciliation)后,将计算出的 DOM 变更应用到实际的 DOM 树上。
- commitLayoutEffects,是 React 提交阶段(Commit Phase)中的一个关键函数,主要负责执行布局副作用(Layout Effects)。在 React 的渲染流程中,当协调阶段(Reconciliation Phase)完成后,会进入提交阶段,这个阶段会将协调阶段计算出的变更应用到实际的 DOM 上。布局副作用是在 DOM 更新后立即执行的副作用,通常用于获取 DOM 节点的布局信息,如元素的宽度、高度等。
- 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 的清理函数)。它主要处理两类逻辑:
- 子节点删除:当父节点标记为需要删除子节点(
ChildDeletion)时,遍历所有待删除的子节点,执行其被动卸载副作用。 - 子树被动副作用:遍历父节点的子树,对每个子节点调用
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 &¤t.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)的副作用钩子(如 useEffect、useLayoutEffect 等)执行清理操作。在 React 中,副作用钩子可能会返回一个清理函数,用于在组件卸载时进行资源释放、取消订阅等操作,该函数就是负责调用这些清理函数的。
函数参数含义
flags: 类型为HookFlags,是一个位掩码,用于筛选需要执行卸载操作的副作用钩子。不同的标志代表不同类型的副作用钩子,例如Layout标志可能对应useLayoutEffect,Passive标志可能对应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;
相关文章:
React19源码阅读之commitRoot
commitRoot入口 在finishConcurrentRender函数,commitRootWhenReady函数,commitRoot函数。 commitRoot流程图 commitRoot函数 commitRoot 函数是 React 渲染流程中用于提交根节点的关键函数。它的主要作用是设置相关的优先级和状态,然后调…...
目标检测:视觉系统中的CNN-Transformer融合网络
一、背景 无人机(UAVs)在城市自动巡逻中发挥着重要作用,但它们在图像识别方面面临挑战,尤其是小目标检测和目标遮挡问题。此外,无人机的高速飞行要求检测系统具备实时处理能力。 为解决这些问题,我们提出…...
Turso:一个基于 libSQL的分布式数据库
Turso 是一个完全托管的数据库平台,支持在一个组织中创建高达数十万个数据库,并且可以复制到任何地点,包括你自己的服务器,以实现微秒级的访问延迟。你可以通过Turso CLI(命令行界面)管理群组、数据库和API…...
深度学习前沿 | TransNeXt:仿生聚合注意力引领视觉感知新时代
目录 1. 引言 2. 背景与挑战 3. TransNeXt 核心创新 3.1 像素聚合注意力(PAA) 3.2 长度缩放余弦注意力(LSCA) 3.3 卷积 GLU(ConvGLU) 4. 模型架构详解 5. 实验与性能评估 5.1 图像分类(I…...
C语言-函数-1
以下是我初学C语言的笔记记录,欢迎在评论区留言补充 一,函数分为几类 * 函数分为两类: 一类是库函数;一类是自定义函数 * 库函数: 系统自己带的,在使用时候,要用到头文件; 查询库函…...
卡尔曼滤波解释及示例
卡尔曼滤波的本质是用数学方法平衡预测与观测的可信度 ,通过不断迭代逼近真实状态。其高效性和鲁棒性,通常在导航定位中,需要融合GPS、加速度计、陀螺仪、激光雷达或摄像头数据,来提高位置精度。简单讲,卡尔曼滤波就是…...
openwrt作旁路由时的几个常见问题 openwrt作为旁路由配置zerotier 图文讲解
1 先看openwrt时间,一定要保证时间和浏览器和服务器是一致的,不然无法更新 2 openwrt设置旁路由前先测试下,路由器能否ping通主路由,是否能够连接外网,好多旁路由设置完了,发现还不能远程好多就是旁路由本…...
Redis--预备知识以及String类型
目录 一、预备知识 1.1 基本全局命令 1.1.1 KEYS 1.1.2 EXISTS 1.1.3 DEL 1.1.4 EXPIRE 1.1.5 TTL 1.1.6 TYPE 1.2 数据结构以及内部编码 1.3 单线程架构 二、String字符串 2.1 常见命令 2.1.1 SET 2.1.2 GET 2.1.3 MGET 2.1.4 MSET 2.1.5 SETNX 2.2 计数命令 2.2.1 INCR 2.2.2…...
Redis 及其在系统设计中的作用
什么是Redis Redis 是一个开源的内存数据结构存储系统,可用作数据库、缓存和消息代理。它因其快速的性能、灵活性和易用性而得到广泛应用。 Redis 数据存储类型 Redis 允许开发人员以各种数据结构(例如字符串、位图、位域、哈希、列表、集合、有序集合…...
UEC++第10天|UEC++获取对象、RTTI是C++
最近在写UEC项目,这里写几个案例里的问题,还在学习阶段 1. 如何获取小鸟对象? void AFlappyBirdGameModeBase::BeginGame() { // 让管道动起来PipeActor->SetMoveSpeed();// 让小鸟开始飞行// 如何获取到小鸟对象APawn* Pawn UGameplayS…...
【python】一文掌握 markitdown 库的操作(用于将文件和办公文档转换为Markdown的Python工具)
更多内容请见: python3案例和总结-专栏介绍和目录 文章目录 一、markitdown概述1.1 markitdown介绍1.2 MarkItDown支持的文件1.3 为什么是Markdown?二、markitdown安装2.1 pip方式安装2.2 源码安装2.3 docker方式安装三、基本使用3.1 命令行方式3.2 可选依赖项配置3.3 插件方…...
爬虫-oiwiki
我们将BASE_URL 设置为 "https://oi-wiki.org/" 后脚本就会自动开始抓取该url及其子页面的所有内容,并将统一子页面的放在一个文件夹中 import requests from bs4 import BeautifulSoup from urllib.parse import urljoin, urlparse import os import pd…...
日语学习-日语知识点小记-构建基础-JLPT-N4阶段(10): つもり 计划/打算
日语学习-日语知识点小记-构建基础-JLPT-N4阶段(10): つもり 计划/打算 1、前言(1)情况说明(2)工程师的信仰 2、知识点(1)つもり 计划/打算(2&a…...
强化学习核心原理及数学框架
1. 定义与核心思想 强化学习(Reinforcement Learning, RL)是一种通过智能体(Agent)与环境(Environment)的持续交互来学习最优决策策略的机器学习范式。其核心特征为: 试错学习&#x…...
【技术派后端篇】技术派中 Session/Cookie 与 JWT 身份验证技术的应用及实现解析
在现代Web应用开发中,身份验证是保障系统安全的重要环节。技术派在身份验证领域采用了多种技术方案,其中Session/Cookie和JWT(JSON Web Token)是两种常用的实现方式。本文将详细介绍这两种身份验证技术在技术派中的应用及具体实现…...
【基础】Node.js 介绍、安装及npm 和 npx功能了解
前言 后面安装n8n要用到,做一点技术储备。主要是它的两个工具:npm 和 npx。 Node.js介绍 Node.js 是一个免费的、开源的、跨平台的 JavaScript 运行时环境,允许开发人员在浏览器之外编写命令行工具和服务器端脚本,是一个基于 C…...
第53讲 农学科研中的AI伦理与可解释性——探索SHAP值、LIME等可解释工具与科研可信性建设之道
目录 一、为什么农学科研中需要“可解释AI”? ✅ 场景示例: 二、常见可解释AI工具介绍 1. SHAP(SHapley Additive exPlanations) 2. LIME(Local Interpretable Model-agnostic Explanations) 三、AI伦理问题在农学中的体现 🧭 公平性与偏见 🔐 数据隐私 🤖…...
助力网站优化利用AI批量生成文章工具提升质量
哎,有时候觉得写东西这事儿吧,真挺玄乎的。你看着那些大网站的优质内容,会不会突然冒出个念头——这些家伙到底怎么做到日更十篇还不秃头的?前阵子我蹲在咖啡馆里盯着屏幕发呆,突然刷到个帖子说现在用AI写文章能自动纠…...
Java语言的进化:JDK的未来版本
作为一名Java开发者,我们正处在一个令人兴奋的时代!Java语言正在以前所未有的速度进化,每个新版本都带来令人惊喜的特性。让我们一起探索JDK未来版本的发展方向,看看Java将如何继续领跑编程语言界!💪 &…...
SpringBootTest报错
Unable to find a SpringBootConfiguration, you need to use ContextConfiguration or … 解决方案:在SpringTest注解中添加属性(classes )填写启动类 如我的启动类是MainApplication.class javax.websocket.server.ServerContainer no…...
Flask + ajax上传文件(二)--多文件上传
Flask多文件上传完整教程 本教程将详细介绍如何使用Flask实现多文件上传功能,并使用时间戳为上传文件自动命名,避免文件名冲突。 一、环境准备 确保已安装Python和Flask pip install flask项目结构 flask_upload/ ├── app.py ├── upload/ # 上传文…...
w~视觉~合集3
我自己的原文哦~ https://blog.51cto.com/whaosoft/12327888 #几个论文 Fast Charging of Energy-dense Lithium-ion Batteries Real-time Short Video Recommendation on Mobile Devices Semantic interpretation for convolutional neural networks: What makes a ca…...
Redis安装及入门应用
应用资料:https://download.csdn.net/download/ly1h1/90685065 1.获取文件,并在该文件下执行cmd 2.输入redis-server-lucifer.exe redis.windows.conf,即可运行redis 3.安装redis客户端软件 4.安装后运行客户端软件,输入链接地址…...
NODE_OPTIONS=--openssl-legacy-provider vue-cli-service serve
//"dev": " NODE_OPTIONS--openssl-legacy-provider vue-cli-service serve" // 修改后(Windows 适用) "dev": "vue-cli-service serve --openssl-legacy-provider" 升级 Node.js 到 v14,确保依赖…...
如何在 Postman 中,自动获取 Token 并将其赋值到环境变量
在 Postman 中,你可以通过 预请求脚本(Pre-request Script) 和 测试脚本(Tests) 实现自动获取 Token 并将其赋值到环境变量,下面是完整的操作步骤: ✅ 一、创建获取 Token 的请求 通常这个请求…...
上篇:深入剖析 BLE 底层物理层与链路层(约5000字)
引言 在无线通信领域,Bluetooth Low Energy(BLE)以其超低功耗、灵活的连接模式和良好的生态支持,成为 IoT 与可穿戴设备的首选技术。要想在实际项目中优化性能、控制功耗、保证可靠通信,必须对 BLE 协议栈的底层细节有深入了解。本篇将重点围绕物理层(PHY)与链路层(Li…...
PostgreSQL 的 MVCC 机制了解
PostgreSQL 的 MVCC 机制了解 PostgreSQL 使用多版本并发控制(MVCC)作为其核心并发控制机制,这是它与许多其他数据库系统的关键区别之一。MVCC 允许读操作不阻塞写操作,写操作也不阻塞读操作,从而提供高度并发性。 一 MVCC 基本原理 1.1 M…...
【Pandas】pandas DataFrame dot
Pandas2.2 DataFrame Binary operator functions 方法描述DataFrame.add(other)用于执行 DataFrame 与另一个对象(如 DataFrame、Series 或标量)的逐元素加法操作DataFrame.add(other[, axis, level, fill_value])用于执行 DataFrame 与另一个对象&…...
2025 年“泰迪杯”数据挖掘挑战赛B题——基于穿戴装备的身体活动监测问题分析
摘要 本文聚焦于基于穿戴设备采集的加速度计数据,深入研究志愿者在日常活动中的行为特征,构建了多个数学建模框架,实现从身体活动监测、能耗预测、睡眠阶段识别到久坐预警等多个目标。我们依托于多源数据融合与机器学习模型,对人体活动状态进行识别与分析,为健康管理、行…...
Vivado版本升级后AXI4-Stream Data FIFO端口变化
Vivado 2017.4版本中异步AXI4-Stream Data FIFO升级到Vivado 2018.3后,IP管脚会发生变化,2018.3版中没有m_axis_aresetn和axis_data_count。 async_axis_fifo_8_1024 async_axis_fifo_8_1024 ( .s_axis_aresetn (I_do0_rstn ), // input wire…...
