From d1dd7feabc63bf8ca61e9b3f4d78245a29ebbe9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Markb=C3=A5ge?= Date: Sat, 14 Dec 2024 13:46:21 -0500 Subject: [PATCH] [Fiber] Schedule client renders using non-hydration lane (#31776) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Related to #31752. When hydrating, we have two different ways of handling a Suspense boundary that the server has already given up on and decided to client render. If we have already hydrated the parent and then later this happens, then we'll use the retry lane like any ping. If we discover that it was already in client-render mode when we discover the Suspense boundary for the first time, then schedule a default lane to let us first finish the current render and then upgrade the priority to sync to try to client render this boundary as soon as possible since we're holding back content. We used to use the `DefaultHydrationLane` for this but this is not really a Hydration. It's actually a client render. If we get any other updates flowing in from above at the same time we might as well do them in the same pass instead of two passes. So this should be considered more like any update. This also means that visually the client render pass now gets painted as a render instead of a hydration. This show the flow of a shell being hydrated at the default priority, then a Suspense boundary being discovered and hydrated at Idle and then an inner boundary being discovered as client rendered which gets upgraded to default. Screenshot 2024-12-14 at 12 13 57 AM --- packages/react-reconciler/src/ReactFiberBeginWork.js | 12 +++++------- packages/shared/ReactFeatureFlags.js | 4 ++-- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/packages/react-reconciler/src/ReactFiberBeginWork.js b/packages/react-reconciler/src/ReactFiberBeginWork.js index 119129d506..0ae0e668d2 100644 --- a/packages/react-reconciler/src/ReactFiberBeginWork.js +++ b/packages/react-reconciler/src/ReactFiberBeginWork.js @@ -111,6 +111,7 @@ import { disableLegacyMode, disableDefaultPropsExceptForClasses, enableOwnerStacks, + enableHydrationLaneScheduling, } from 'shared/ReactFeatureFlags'; import isArray from 'shared/isArray'; import shallowEqual from 'shared/shallowEqual'; @@ -146,6 +147,7 @@ import { NoLane, NoLanes, OffscreenLane, + DefaultLane, DefaultHydrationLane, SomeRetryLane, includesSomeLane, @@ -2646,14 +2648,10 @@ function mountDehydratedSuspenseComponent( // have timed out. In theory we could render it in this pass but it would have the // wrong priority associated with it and will prevent hydration of parent path. // Instead, we'll leave work left on it to render it in a separate commit. - - // TODO This time should be the time at which the server rendered response that is - // a parent to this boundary was displayed. However, since we currently don't have - // a protocol to transfer that time, we'll just estimate it by using the current - // time. This will mean that Suspense timeouts are slightly shifted to later than - // they should be. // Schedule a normal pri update to render this content. - workInProgress.lanes = laneToLanes(DefaultHydrationLane); + workInProgress.lanes = laneToLanes( + enableHydrationLaneScheduling ? DefaultLane : DefaultHydrationLane, + ); } else { // We'll continue hydrating the rest at offscreen priority since we'll already // be showing the right content coming from the server, it is no rush. diff --git a/packages/shared/ReactFeatureFlags.js b/packages/shared/ReactFeatureFlags.js index f28d123e61..afac564cad 100644 --- a/packages/shared/ReactFeatureFlags.js +++ b/packages/shared/ReactFeatureFlags.js @@ -22,6 +22,8 @@ // when it rolls out to prod. We should remove these as soon as possible. // ----------------------------------------------------------------------------- +export const enableHydrationLaneScheduling = true; + // ----------------------------------------------------------------------------- // Land or remove (moderate effort) // @@ -111,8 +113,6 @@ export const enableSuspenseAvoidThisFallback = false; export const enableCPUSuspense = __EXPERIMENTAL__; -export const enableHydrationLaneScheduling = true; - // Test this at Meta before enabling. export const enableNoCloningMemoCache = false;