Skip to content

Commit 961b625

Browse files
authored
Try not. Do... or do not. Hydrate Suspense Boundaries. (#32851)
Assertively claim a SuspenseInstance. We already know we're hydrating. If there's no match, it throws anyway. So there's no other code path.
1 parent 8a3c5e1 commit 961b625

File tree

2 files changed

+22
-30
lines changed

2 files changed

+22
-30
lines changed

packages/react-reconciler/src/ReactFiberBeginWork.js

Lines changed: 9 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,6 @@ import {
203203
pushFallbackTreeSuspenseHandler,
204204
pushOffscreenSuspenseHandler,
205205
reuseSuspenseHandlerOnStack,
206-
popSuspenseHandler,
207206
} from './ReactFiberSuspenseContext';
208207
import {
209208
pushHiddenContext,
@@ -245,7 +244,7 @@ import {
245244
claimHydratableSingleton,
246245
tryToClaimNextHydratableInstance,
247246
tryToClaimNextHydratableTextInstance,
248-
tryToClaimNextHydratableSuspenseInstance,
247+
claimNextHydratableSuspenseInstance,
249248
warnIfHydrating,
250249
queueHydrationError,
251250
} from './ReactFiberHydrationContext';
@@ -2151,24 +2150,14 @@ function updateSuspenseComponent(
21512150
} else {
21522151
pushFallbackTreeSuspenseHandler(workInProgress);
21532152
}
2154-
tryToClaimNextHydratableSuspenseInstance(workInProgress);
2155-
// This could've been a dehydrated suspense component.
2156-
const suspenseState: null | SuspenseState = workInProgress.memoizedState;
2157-
if (suspenseState !== null) {
2158-
const dehydrated = suspenseState.dehydrated;
2159-
if (dehydrated !== null) {
2160-
return mountDehydratedSuspenseComponent(
2161-
workInProgress,
2162-
dehydrated,
2163-
renderLanes,
2164-
);
2165-
}
2166-
}
2167-
// If hydration didn't succeed, fall through to the normal Suspense path.
2168-
// To avoid a stack mismatch we need to pop the Suspense handler that we
2169-
// pushed above. This will become less awkward when move the hydration
2170-
// logic to its own fiber.
2171-
popSuspenseHandler(workInProgress);
2153+
// This throws if we fail to hydrate.
2154+
const dehydrated: SuspenseInstance =
2155+
claimNextHydratableSuspenseInstance(workInProgress);
2156+
return mountDehydratedSuspenseComponent(
2157+
workInProgress,
2158+
dehydrated,
2159+
renderLanes,
2160+
);
21722161
}
21732162

21742163
const nextPrimaryChildren = nextProps.children;

packages/react-reconciler/src/ReactFiberHydrationContext.js

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,10 @@ function tryHydrateText(fiber: Fiber, nextInstance: any) {
272272
return false;
273273
}
274274

275-
function tryHydrateSuspense(fiber: Fiber, nextInstance: any) {
275+
function tryHydrateSuspense(
276+
fiber: Fiber,
277+
nextInstance: any,
278+
): null | SuspenseInstance {
276279
// fiber is a SuspenseComponent Fiber
277280
const suspenseInstance = canHydrateSuspenseInstance(
278281
nextInstance,
@@ -298,9 +301,8 @@ function tryHydrateSuspense(fiber: Fiber, nextInstance: any) {
298301
// While a Suspense Instance does have children, we won't step into
299302
// it during the first pass. Instead, we'll reenter it later.
300303
nextHydratableInstance = null;
301-
return true;
302304
}
303-
return false;
305+
return suspenseInstance;
304306
}
305307

306308
export const HydrationMismatchException: mixed = new Error(
@@ -423,15 +425,16 @@ function tryToClaimNextHydratableTextInstance(fiber: Fiber): void {
423425
}
424426
}
425427

426-
function tryToClaimNextHydratableSuspenseInstance(fiber: Fiber): void {
427-
if (!isHydrating) {
428-
return;
429-
}
428+
function claimNextHydratableSuspenseInstance(fiber: Fiber): SuspenseInstance {
430429
const nextInstance = nextHydratableInstance;
431-
if (!nextInstance || !tryHydrateSuspense(fiber, nextInstance)) {
430+
const suspenseInstance = nextInstance
431+
? tryHydrateSuspense(fiber, nextInstance)
432+
: null;
433+
if (suspenseInstance === null) {
432434
warnNonHydratedInstance(fiber, nextInstance);
433-
throwOnHydrationMismatch(fiber);
435+
throw throwOnHydrationMismatch(fiber);
434436
}
437+
return suspenseInstance;
435438
}
436439

437440
export function tryToClaimNextHydratableFormMarkerInstance(
@@ -790,7 +793,7 @@ export {
790793
claimHydratableSingleton,
791794
tryToClaimNextHydratableInstance,
792795
tryToClaimNextHydratableTextInstance,
793-
tryToClaimNextHydratableSuspenseInstance,
796+
claimNextHydratableSuspenseInstance,
794797
prepareToHydrateHostInstance,
795798
prepareToHydrateHostTextInstance,
796799
prepareToHydrateHostSuspenseInstance,

0 commit comments

Comments
 (0)