Fiber 工作循环?循环工作? Who care?
一、作用
二、导出的常量
1.上下文常量
备注
源码中的 408 - 411 行
// 无上下文
export const NoContext = 0b000;
// 渲染上下文
export const RenderContext = 0b010;
// 提交上下文
export const CommitContext = 0b100;
2. 交叉渲染 Lane
备注
源码中的 464 - 472 行
// A contextual version of workInProgressRootRenderLanes. It is a superset of
// the lanes that we started working on at the root. When we enter a subtree
// that is currently hidden, we add the lanes that would have committed if
// the hidden tree hadn't been deferred. This is modified by the
// HiddenContext module.
//
// workInProgressRootRenderLanes 的上下文版本。
// 它是我们在根节点开始工作的车道的超集。
// 当我们进入一个当前被隐藏的子树时,我们会添加如果隐藏树没有被延迟而会提交的车道。
// 这会被 HiddenContext 模块修改。
//
// Most things in the work loop should deal with workInProgressRootRenderLanes.
// Most things in begin/complete phases should deal with entangledRenderLanes.
//
// 工作循环中的大多数内容应该处理 workInProgressRootRenderLanes。
// 开始/完成阶段中的大多数内容应该处理 entangledRenderLanes。
export let entangledRenderLanes: Lanes = NoLanes;
三、 获取进行中的工作转换
export function getWorkInProgressTransitions(): null | Array<Transition> {
return workInProgressTransitions;
}
四、 向待处理过渡添加回调
1.向待处理过渡添加开始回调
export function addTransitionStartCallbackToPendingTransition(
transition: Transition,
) {
if (enableTransitionTracing) {
if (currentPendingTransitionCallbacks === null) {
currentPendingTransitionCallbacks = {
transitionStart: [],
transitionProgress: null,
transitionComplete: null,
markerProgress: null,
markerIncomplete: null,
markerComplete: null,
};
}
if (currentPendingTransitionCallbacks.transitionStart === null) {
currentPendingTransitionCallbacks.transitionStart =
[] as Array<Transition>;
}
currentPendingTransitionCallbacks.transitionStart.push(transition);
}
}
2.向待处理过渡添加标记进度回调
export function addMarkerProgressCallbackToPendingTransition(
markerName: string,
transitions: Set<Transition>,
pendingBoundaries: PendingBoundaries,
) {
if (enableTransitionTracing) {
if (currentPendingTransitionCallbacks === null) {
currentPendingTransitionCallbacks = {
transitionStart: null,
transitionProgress: null,
transitionComplete: null,
markerProgress: new Map(),
markerIncomplete: null,
markerComplete: null,
} as PendingTransitionCallbacks;
}
if (currentPendingTransitionCallbacks.markerProgress === null) {
currentPendingTransitionCallbacks.markerProgress = new Map();
}
currentPendingTransitionCallbacks.markerProgress.set(markerName, {
pendingBoundaries,
transitions,
});
}
}
3. 向待处理过渡添加标记不完整回调
export function addMarkerIncompleteCallbackToPendingTransition(
markerName: string,
transitions: Set<Transition>,
aborts: Array<TransitionAbort>,
) {
if (enableTransitionTracing) {
if (currentPendingTransitionCallbacks === null) {
currentPendingTransitionCallbacks = {
transitionStart: null,
transitionProgress: null,
transitionComplete: null,
markerProgress: null,
markerIncomplete: new Map(),
markerComplete: null,
};
}
if (currentPendingTransitionCallbacks.markerIncomplete === null) {
currentPendingTransitionCallbacks.markerIncomplete = new Map();
}
currentPendingTransitionCallbacks.markerIncomplete.set(markerName, {
transitions,
aborts,
});
}
}
4. 向待处理过渡添加标记完成回调
export function addMarkerCompleteCallbackToPendingTransition(
markerName: string,
transitions: Set<Transition>,
) {
if (enableTransitionTracing) {
if (currentPendingTransitionCallbacks === null) {
currentPendingTransitionCallbacks = {
transitionStart: null,
transitionProgress: null,
transitionComplete: null,
markerProgress: null,
markerIncomplete: null,
markerComplete: new Map(),
};
}
if (currentPendingTransitionCallbacks.markerComplete === null) {
currentPendingTransitionCallbacks.markerComplete = new Map();
}
currentPendingTransitionCallbacks.markerComplete.set(
markerName,
transitions,
);
}
}
5. 向待处理过渡添加进度回调
export function addTransitionProgressCallbackToPendingTransition(
transition: Transition,
boundaries: PendingBoundaries,
) {
if (enableTransitionTracing) {
if (currentPendingTransitionCallbacks === null) {
currentPendingTransitionCallbacks = {
transitionStart: null,
transitionProgress: new Map(),
transitionComplete: null,
markerProgress: null,
markerIncomplete: null,
markerComplete: null,
};
}
if (currentPendingTransitionCallbacks.transitionProgress === null) {
currentPendingTransitionCallbacks.transitionProgress = new Map();
}
currentPendingTransitionCallbacks.transitionProgress.set(
transition,
boundaries,
);
}
}
6. 向待处理过渡添加完成回调
export function addTransitionCompleteCallbackToPendingTransition(
transition: Transition,
) {
if (enableTransitionTracing) {
if (currentPendingTransitionCallbacks === null) {
currentPendingTransitionCallbacks = {
transitionStart: null,
transitionProgress: null,
transitionComplete: [],
markerProgress: null,
markerIncomplete: null,
markerComplete: null,
};
}
if (currentPendingTransitionCallbacks.transitionComplete === null) {
currentPendingTransitionCallbacks.transitionComplete =
[] as Array<Transition>;
}
currentPendingTransitionCallbacks.transitionComplete.push(transition);
}
}
五、 获取渲染目标的时间
export function getRenderTargetTime(): number {
return workInProgressRootRenderTargetTime;
}
六、获取变量
1. 获取进行中的根
export function getWorkInProgressRoot(): FiberRoot | null {
return workInProgressRoot;
}
2. 获取提交根
export function getCommittingRoot(): FiberRoot | null {
return pendingEffectsRoot;
}
3. 获取正在进行的根渲染 Lanes
export function getWorkInProgressRootRenderLanes(): Lanes {
return workInProgressRootRenderLanes;
}
4. 有待提交的效果
export function hasPendingCommitEffects(): boolean {
return (
pendingEffectsStatus !== NO_PENDING_EFFECTS &&
pendingEffectsStatus !== PENDING_PASSIVE_PHASE
);
}
5. 获取具有待处理被动效果的根
export function getRootWithPendingPassiveEffects(): FiberRoot | null {
return pendingEffectsStatus === PENDING_PASSIVE_PHASE
? pendingEffectsRoot
: null;
}
6. 获取待处理的被动效果 Lanes
export function getPendingPassiveEffectsLanes(): Lanes {
return pendingEffectsLanes;
}
7. 获取待处理过渡类型
export function getPendingTransitionTypes(): null | TransitionTypes {
return pendingTransitionTypes;
}
8. 工作循环是否在数据上挂起
export function isWorkLoopSuspendedOnData(): boolean {
return (
workInProgressSuspendedReason === SuspendedOnData ||
workInProgressSuspendedReason === SuspendedOnAction
);
}
9. 获取当前时间
export function getCurrentTime(): number {
return now();
}
七、请求更新 Lane
信息
disableLegacyMode在 shared 中ConcurrentMode在 ReactTypeOfMode 中pickArbitraryLane()由 ReactFiberLane#pickArbitraryLane 实现requestCurrentTransition()由 ReactFiberTransition#requestCurrentTransition 实现requestTransitionLane()由 ReactFiberRootScheduler#requestTransitionLane 实现eventPriorityToLane()由 ReactEventPriorities#eventPriorityToLane 实现resolveUpdatePriority()由渲染平台实现
export function requestUpdateLane(fiber: Fiber): Lane {
// Special cases
// 特殊情况
const mode = fiber.mode;
if (!disableLegacyMode && (mode & ConcurrentMode) === NoMode) {
return SyncLane as Lane;
} else if (
(executionContext & RenderContext) !== NoContext &&
workInProgressRootRenderLanes !== NoLanes
) {
// This is a render phase update. These are not officially supported. The
// old behavior is to give this the same "thread" (lanes) as
// whatever is currently rendering. So if you call `setState` on a component
// that happens later in the same render, it will flush. Ideally, we want to
// remove the special case and treat them as if they came from an
// interleaved event. Regardless, this pattern is not officially supported.
// This behavior is only a fallback. The flag only exists until we can roll
// out the setState warning, since existing code might accidentally rely on
// the current behavior.
//
// 这是一次渲染阶段的更新。这些不是官方支持的。
// 旧的行为是给它同样的“线程”(lane)作为
// 当前正在渲染的内容。因此,如果你在同一次渲染中稍后调用组件的 `setState`,
// 它会立即刷新。理想情况下,我们希望移除这个特殊情况,并把它们当作来自交错事件的更新处理。
// 不管怎样,这种模式不是官方支持的。
// 这种行为仅仅是一个回退。这个标志的存在只是为了在我们推出 setState 警告之前,
// 因为现有代码可能偶尔依赖于当前行为。
return pickArbitraryLane(workInProgressRootRenderLanes);
}
const transition = requestCurrentTransition();
if (transition !== null) {
if (enableGestureTransition) {
if (transition.gesture) {
throw new Error(
'Cannot setState on regular state inside a startGestureTransition. ' +
'Gestures can only update the useOptimistic() hook. There should be no ' +
'side-effects associated with starting a Gesture until its Action is ' +
'invoked. Move side-effects to the Action instead.',
);
}
}
if (__DEV__) {
if (!transition._updatedFibers) {
transition._updatedFibers = new Set();
}
transition._updatedFibers.add(fiber);
}
return requestTransitionLane(transition);
}
return eventPriorityToLane(resolveUpdatePriority());
}
八、请求延迟车道
信息
includesSomeLane()由 ReactFiberLane#includesSomeLane 实现
export function requestDeferredLane(): Lane {
if (workInProgressDeferredLane === NoLane) {
// If there are multiple useDeferredValue hooks in the same render, the
// tasks that they spawn should all be batched together, so they should all
// receive the same lane.
//
// 如果在同一次渲染中有多个 useDeferredValue 钩子,它们生成的任务应该全部批量
// 处理,因此它们都应该接收相同的通道。
// Check the priority of the current render to decide the priority of the
// deferred task.
//
// 检查当前渲染的优先级,以决定延迟任务的优先级。
// OffscreenLane is used for prerendering, but we also use OffscreenLane
// for incremental hydration. It's given the lowest priority because the
// initial HTML is the same as the final UI. But useDeferredValue during
// hydration is an exception — we need to upgrade the UI to the final
// value. So if we're currently hydrating, we treat it like a transition.
//
// OffscreenLane 用于预渲染,但我们也使用 OffscreenLane 进行增量 hydration。
// 它的优先级最低,因为初始 HTML 与最终 UI 相同。
// 但在 hydration 期间使用 useDeferredValue 是一个例外 —— 我们需要将 UI 升级到
// 最终值。所以如果我们当前正在进行 hydration,我们会将其视为一次过渡。
const isPrerendering =
includesSomeLane(workInProgressRootRenderLanes, OffscreenLane) &&
!getIsHydrating();
if (isPrerendering) {
// There's only one OffscreenLane, so if it contains deferred work, we
// should just reschedule using the same lane.
//
// 只有一个离屏赛道,所以如果它包含延迟工作,
// 我们应该使用相同的赛道重新调度。
workInProgressDeferredLane = OffscreenLane;
} else {
// Everything else is spawned as a transition.
// 其他所有内容都是作为过渡生成的。
workInProgressDeferredLane = claimNextTransitionDeferredLane();
}
}
// Mark the parent Suspense boundary so it knows to spawn the deferred lane.
// 标记父级 Suspense 边界,以便它知道生成延迟通道。
const suspenseHandler = getSuspenseHandler();
if (suspenseHandler !== null) {
// TODO: As an optimization, we shouldn't entangle the lanes at the root; we
// can entangle them using the baseLanes of the Suspense boundary instead.
// We only need to do something special if there's no Suspense boundary.
//
// 待办:作为一种优化,我们不应该在根节点纠缠这些 lanes;
// 我们可以使用 Suspense 边界的 baseLanes 来纠缠它们。
// 只有在没有 Suspense 边界时,我们才需要做一些特别处理。
suspenseHandler.flags |= DidDefer;
}
return workInProgressDeferredLane;
}
常数
1. WeakMap 可用
备注
原文中 404 行
const PossiblyWeakMap = typeof WeakMap === 'function' ? WeakMap : Map;
2. 批处理上下文
备注
原文 409 行
const BatchedContext = 0b001;
3. 根
备注
源码中 413 - 420 行
注意
奇怪,不想 React 的风格,不应当创建一个名为 「ReactFiberRootFlags」 文件
// 正在获取根权限
const RootInProgress = 0;
// 根致命错误
const RootFatalErrored = 1;
// 根错误
const RootErrored = 2;
// 根悬挂
const RootSuspended = 3;
// 延迟挂起根
const RootSuspendedWithDelay = 4;
// 根部悬挂在壳上
const RootSuspendedAtTheShell = 6;
// 根目录完成
const RootCompleted = 5;
4. 暂停
备注
原文中 431 - 441 行
export type SuspendedReason = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9;
// 未暂停
const NotSuspended: SuspendedReason = 0;
// 因错误而暂停
const SuspendedOnError: SuspendedReason = 1;
// 挂起而等待数据
const SuspendedOnData: SuspendedReason = 2;
// 因 Immediate 而暂停
const SuspendedOnImmediate: SuspendedReason = 3;
// 因实例而暂停
const SuspendedOnInstance: SuspendedReason = 4;
// 因实例而暂停,准备继续
const SuspendedOnInstanceAndReadyToContinue: SuspendedReason = 5;
// 因弃用的 throw Promise 而挂起
const SuspendedOnDeprecatedThrowPromise: SuspendedReason = 6;
// 暂停后重试并继续
const SuspendedAndReadyToContinue: SuspendedReason = 7;
// 挂起以等待水合
const SuspendedOnHydration: SuspendedReason = 8;
// 挂起等待处理事件
const SuspendedOnAction: SuspendedReason = 9;
5. 提交状态/类型
备注
源码中的 702 - 708 hang
type SuspendedCommitReason = null | string;
type DelayedCommitReason = 0 | 1 | 2 | 3;
// 立即提交
const IMMEDIATE_COMMIT = 0;
// 已中止视图过渡提交
const ABORTED_VIEW_TRANSITION_COMMIT = 1;
// 延迟被动提交
const DELAYED_PASSIVE_COMMIT = 2;
// 动画已开始提交
const ANIMATION_STARTED_COMMIT = 3;
6. 待处理
备注
源码中的 710 - 717
const NO_PENDING_EFFECTS = 0; // 无待处理效果
const PENDING_MUTATION_PHASE = 1; // 待定变异阶段
const PENDING_LAYOUT_PHASE = 2; // 待布局阶段
const PENDING_AFTER_MUTATION_PHASE = 3; // 变异后待处理
const PENDING_SPAWNED_WORK = 4; // 待生成的工作
const PENDING_PASSIVE_PHASE = 5; // 待被动阶段
const PENDING_GESTURE_MUTATION_PHASE = 6; // 待处理手势变更阶段
const PENDING_GESTURE_ANIMATION_PHASE = 7; // 待处理手势动画阶段
7. 嵌套更新限制
// Use these to prevent an infinite loop of nested updates
// 使用这些来防止嵌套更新的无限循环
const NESTED_UPDATE_LIMIT = 50;
8. 嵌套被动更新限制
备注
源码中的 742 行
const NESTED_PASSIVE_UPDATE_LIMIT = 50;
变量
1. 备用 Fiber
备注
原文中 422 - 429 行
// Describes where we are in the React execution stack
// 描述我们在 React 执行栈中的位置
let executionContext: ExecutionContext = NoContext;
// The root we're working on
// 正在处理的根
let workInProgressRoot: FiberRoot | null = null;
// The fiber we're working on
// 正在处理的 Fiber
let workInProgress: Fiber | null = null;
// The lanes we're rendering
// 准备渲染的 Lane
let workInProgressRootRenderLanes: Lanes = NoLanes;
2. 处理中的值
备注
源码中 443 - 462
// When this is true, the work-in-progress fiber just suspended (or errored) and
// we've yet to unwind the stack. In some cases, we may yield to the main thread
// after this happens. If the fiber is pinged before we resume, we can retry
// immediately instead of unwinding the stack.
//
// 当这个为真时,正在进行中的 fiber 刚刚被挂起(或出错),而我们尚未清理堆栈。
// 在某些情况下,这发生后我们可能会让出给主线程。
// 如果在我们恢复之前 fiber 收到 ping,我们可以立即重试,而不是清理堆栈。
// 工作进行中暂停原因
let workInProgressSuspendedReason: SuspendedReason = NotSuspended;
// 工作进行中抛出的值
let workInProgressThrownValue: mixed = null;
// Tracks whether any siblings were skipped during the unwind phase after
// something suspends. Used to determine whether to schedule another render
// to prewarm the skipped siblings.
//
// 跟踪在某个操作被挂起后,在展开阶段是否跳过了兄弟节点。
// 用于确定是否需要安排另一轮渲染来预热被跳过的兄弟节点。
//
// workInProgressRoot 跳过了挂起的兄弟节点
let workInProgressRootDidSkipSuspendedSiblings: boolean = false;
// Whether the work-in-progress render is the result of a prewarm/prerender.
// This tells us whether or not we should render the siblings after
// something suspends.
//
// 无论正在进行的渲染是否是预热/预渲染的结果。
// 这告诉我们当某些内容挂起时是否应该渲染兄弟节点。
//
// 正在进行的根正在预渲染
let workInProgressRootIsPrerendering: boolean = false;
// Whether a ping listener was attached during this render. This is slightly
// different that whether something suspended, because we don't add multiple
// listeners to a promise we've already seen (per root and lane).
//
// 在此渲染期间是否附加了 ping 监听器。这与某些内容是否挂起略有不同,
// 因为我们不会对已经见过的 Promise 添加多个监听器(按根和 Lane 分别计算)。
//
// workInProgressRoot 已附加 Ping 监听器
let workInProgressRootDidAttachPingListener: boolean = false;
3. 备用树的状态
备注
源码中的 474 - 523
// Whether to root completed, errored, suspended, etc.
// 是否已完成、出错、挂起等
// 工作进行中根退出状态
let workInProgressRootExitStatus: RootExitStatus = RootInProgress;
// The work left over by components that were visited during this render. Only
// includes unprocessed updates, not work in bailed out children.
//
// 在此次渲染过程中被访问的组件剩余的工作。仅包括未处理的更新,不包括已放弃的子组件中的工作。
// 工作进行中根跳过的通道
let workInProgressRootSkippedLanes: Lanes = NoLanes;
// Lanes that were updated (in an interleaved event) during this render.
// 在此渲染期间(在交错事件中)更新的 Lane
// 进行中根节点交错更新的 Lane
let workInProgressRootInterleavedUpdatedLanes: Lanes = NoLanes;
// Lanes that were updated during the render phase (*not* an interleaved event).
// 在渲染阶段更新的通道(*不是*交错事件)。
// 正在进行的根渲染阶段已更新的 Lane
let workInProgressRootRenderPhaseUpdatedLanes: Lanes = NoLanes;
// Lanes that were pinged (in an interleaved event) during this render.
// 在此次渲染期间(在交错事件中)被 ping 的优先级队列。
// 正在进行中的根节点已触发的 Lane
let workInProgressRootPingedLanes: Lanes = NoLanes;
// If this render scheduled deferred work, this is the lane of the deferred task.
// 如果此渲染调度了延迟工作,这就是延迟任务的 Lane
// 工作进行中延迟 Lane
let workInProgressDeferredLane: Lane = NoLane;
// Represents the retry lanes that were spawned by this render and have not
// been pinged since, implying that they are still suspended.
//
// 表示由此渲染生成且自那时起未被触发的重试 Lane,这意味着它们仍然处于挂起状态。
// 工作进展暂停重试 Lane
let workInProgressSuspendedRetryLanes: Lanes = NoLanes;
// Errors that are thrown during the render phase.
// 在并发渲染阶段抛出的错误。
let workInProgressRootConcurrentErrors: Array<CapturedValue<mixed>> | null =
null;
// These are errors that we recovered from without surfacing them to the UI.
// We will log them once the tree commits.
//
// 这些是我们恢复过来的错误,但没有显示在用户界面上。
// 一旦树提交,我们会记录它们。
// 工作进行中根可恢复错误
let workInProgressRootRecoverableErrors: Array<CapturedValue<mixed>> | null =
null;
// Tracks when an update occurs during the render phase.
// 跟踪在渲染阶段发生更新的情况。
let workInProgressRootDidIncludeRecursiveRenderUpdate: boolean = false;
// Thacks when an update occurs during the commit phase. It's a separate
// variable from the one for renders because the commit phase may run
// concurrently to a render phase.
//
// 当在提交阶段发生更新时触发 Thacks。它是一个独立的变量,不同于渲染阶段
// 使用的变量,因为提交阶段可能与渲染阶段并发运行。
let didIncludeCommitPhaseUpdate: boolean = false;
// The most recent time we either committed a fallback, or when a fallback was
// filled in with the resolved UI. This lets us throttle the appearance of new
// content as it streams in, to minimize jank.
// TODO: Think of a better name for this variable?
//
// 我们最近一次采用回退方案,或者用解析后的 UI 填充回退时的时间。这让我们在
// 新的内容流入时能够控制其出现频率,以最小化卡顿。
// TODO: 想一个更好的变量名字?
let globalMostRecentFallbackTime: number = 0;
// Track the most recent time we started a new Transition. This lets us apply
// heuristics like the suspensey image timeout based on how long we've waited
// already.
//
// 跟踪我们最近一次开始新过渡的时间。这让我们可以根据已经等待的时间
// 来应用类似悬念图像超时的启发式方法。
let globalMostRecentTransitionTime: number = 0;
// 回退节流毫秒
const FALLBACK_THROTTLE_MS: number = 300;
// The absolute time for when we should start giving up on rendering
// more and prefer CPU suspense heuristics instead.
//
// 我们应该放弃更多渲染、转而优先使用 CPU 暂停启发式的绝对时间。
let workInProgressRootRenderTargetTime: number = Infinity;
// How long a render is supposed to take before we start following CPU
// suspense heuristics and opt out of rendering more content.
//
// 在我们开始遵循 CPU 暂停启发式并选择不再渲染更多内容之前,渲染应该持续多长时间。
const RENDER_TIMEOUT_MS = 500;
// 进行中转换
let workInProgressTransitions: Array<Transition> | null = null;
4.工作进度
备注
源码中的 528 - 532 行
// The first setState call that eventually caused the current render.
// 第一个 setState 调用,最终导致了当前的渲染。
// 工作进度更新任务
let workInProgressUpdateTask: null | ConsoleTask = null;
// 当前待处理过渡回调
let currentPendingTransitionCallbacks: PendingTransitionCallbacks | null = null;
// 当前结束时间
let currentEndTime: number | null = null;
5. 已失败的旧版错误边界
备注
源码中的 700 行
let legacyErrorBoundariesThatAlreadyFailed: Set<mixed> | null = null;
6. 待处理状态
备注
源码中 718 - 733 行
// 待处理效果状态
let pendingEffectsStatus: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 = 0;
// 待处理效果根
let pendingEffectsRoot: FiberRoot = null as any;
// 待完成工作
let pendingFinishedWork: Fiber = null as any;
// 待处理效果 Lanes
let pendingEffectsLanes: Lanes = NoLanes;
// 待处理效果剩余 Lanes
let pendingEffectsRemainingLanes: Lanes = NoLanes;
// 待处理效果渲染结束时间 (仅限分析)
let pendingEffectsRenderEndTime: number = -0; // Profiling-only
// 待处理的被动过渡
let pendingPassiveTransitions: Array<Transition> | null = null;
// 待恢复错误
let pendingRecoverableErrors: null | Array<CapturedValue<mixed>> = null;
// 待查看过渡
let pendingViewTransition: null | RunningViewTransition = null;
// 待处理视图过渡事件
let pendingViewTransitionEvents: Array<(types: Array<string>) => void> | null =
null;
// 待处理的过渡类型
let pendingTransitionTypes: null | TransitionTypes = null;
// 待处理的渲染阶段更新
let pendingDidIncludeRenderPhaseUpdate: boolean = false;
// 待定/暂停的提交原因(仅限分析)
let pendingSuspendedCommitReason: SuspendedCommitReason = null; // Profiling-only
// 待处理延迟提交原因(仅限分析)
let pendingDelayedCommitReason: DelayedCommitReason = IMMEDIATE_COMMIT; // Profiling-only
// 挂起的暂停视图转换原因(仅限分析)
let pendingSuspendedViewTransitionReason: null | string = null; // Profiling-only
7. 更新
备注
源码中 737 - 740 行
// 嵌套更新计数
let nestedUpdateCount: number = 0;
// 带嵌套更新的根
let rootWithNestedUpdates: FiberRoot | null = null;
// 正在刷新被动效果
let isFlushingPassiveEffects = false;
// 在被动效果期间安排了更新
let didScheduleUpdateDuringPassiveEffects = false;
8. e
备注
源码中的 743 - 746
// 嵌套被动更新计数
let nestedPassiveUpdateCount: number = 0;
// 带被动嵌套更新的根
let rootWithPassiveNestedUpdates: FiberRoot | null = null;
// 正在运行插入效果
let isRunningInsertionEffect = false;
工具
1. 重置渲染时间
function resetRenderTimer() {
workInProgressRootRenderTargetTime = now() + RENDER_TIMEOUT_MS;
}
2. 请求重试通道
备注
claimNextRetryLane()由 ReactFiberLane#claimNextRetryLane 实现
function requestRetryLane(fiber: Fiber) {
// This is a fork of `requestUpdateLane` designed specifically for Suspense
// "retries" — a special update that attempts to flip a Suspense boundary
// from its placeholder state to its primary/resolved state.
//
// 这是 `requestUpdateLane` 的一个分支,专门为 Suspense 设计
// “重试” — 一种特殊的更新,尝试将 Suspense 边界
// 从占位状态切换到其主要/已解析状态。
// Special cases
// 特殊情况
const mode = fiber.mode;
if (!disableLegacyMode && (mode & ConcurrentMode) === NoMode) {
return SyncLane as Lane;
}
return claimNextRetryLane();
}