diff --git a/packages/react-reconciler/src/ReactFiberWorkLoop.js b/packages/react-reconciler/src/ReactFiberWorkLoop.js index 36189aea53ca4..4c20659b69cc0 100644 --- a/packages/react-reconciler/src/ReactFiberWorkLoop.js +++ b/packages/react-reconciler/src/ReactFiberWorkLoop.js @@ -329,8 +329,8 @@ const RootFatalErrored = 1; const RootErrored = 2; const RootSuspended = 3; const RootSuspendedWithDelay = 4; +const RootSuspendedAtTheShell = 6; const RootCompleted = 5; -const RootDidNotComplete = 6; // Describes where we are in the React execution stack let executionContext: ExecutionContext = NoContext; @@ -942,15 +942,6 @@ export function performWorkOnRoot( markRootSuspended(root, lanes, NoLane, didAttemptEntireTree); } break; - } else if (exitStatus === RootDidNotComplete) { - if (enableProfilerTimer && enableComponentPerformanceTrack) { - finalizeRender(lanes, now()); - } - // The render unwound without completing the tree. This happens in special - // cases where need to exit the current render without producing a - // consistent tree or committing. - const didAttemptEntireTree = !workInProgressRootDidSkipSuspendedSiblings; - markRootSuspended(root, lanes, NoLane, didAttemptEntireTree); } else { // The render completed. @@ -998,7 +989,7 @@ export function performWorkOnRoot( // from the beginning. // TODO: Refactor the exit algorithm to be less confusing. Maybe // more branches + recursion instead of a loop. I think the only - // thing that causes it to be a loop is the RootDidNotComplete + // thing that causes it to be a loop is the RootSuspendedAtTheShell // check. If that's true, then we don't need a loop/recursion // at all. continue; @@ -1134,25 +1125,27 @@ function finishConcurrentRender( throw new Error('Root did not complete. This is a bug in React.'); } case RootSuspendedWithDelay: { - if (includesOnlyTransitions(lanes)) { - // This is a transition, so we should exit without committing a - // placeholder and without scheduling a timeout. Delay indefinitely - // until we receive more data. - if (enableProfilerTimer && enableComponentPerformanceTrack) { - finalizeRender(lanes, now()); - } - const didAttemptEntireTree = - !workInProgressRootDidSkipSuspendedSiblings; - markRootSuspended( - root, - lanes, - workInProgressDeferredLane, - didAttemptEntireTree, - ); - return; + if (!includesOnlyTransitions(lanes)) { + // Commit the placeholder. + break; } - // Commit the placeholder. - break; + } + // Fallthrough + case RootSuspendedAtTheShell: { + // This is a transition, so we should exit without committing a + // placeholder and without scheduling a timeout. Delay indefinitely + // until we receive more data. + if (enableProfilerTimer && enableComponentPerformanceTrack) { + finalizeRender(lanes, renderEndTime); + } + const didAttemptEntireTree = !workInProgressRootDidSkipSuspendedSiblings; + markRootSuspended( + root, + lanes, + workInProgressDeferredLane, + didAttemptEntireTree, + ); + return; } case RootErrored: { // This render errored. Ignore any recoverable errors because we weren't actually @@ -2146,7 +2139,7 @@ function renderRootSync( // just yield and reset the stack when we re-enter the work loop, // like normal. resetWorkInProgressStack(); - exitStatus = RootDidNotComplete; + exitStatus = RootSuspendedAtTheShell; break outer; } case SuspendedOnImmediate: @@ -2465,7 +2458,7 @@ function renderRootConcurrent(root: FiberRoot, lanes: Lanes) { // Interrupt the current render so the work loop can switch to the // hydration lane. resetWorkInProgressStack(); - workInProgressRootExitStatus = RootDidNotComplete; + workInProgressRootExitStatus = RootSuspendedAtTheShell; break outer; } default: { @@ -2973,7 +2966,7 @@ function unwindUnitOfWork(unitOfWork: Fiber, skipSiblings: boolean): void { } while (incompleteWork !== null); // We've unwound all the way to the root. - workInProgressRootExitStatus = RootDidNotComplete; + workInProgressRootExitStatus = RootSuspendedAtTheShell; workInProgress = null; }