mirror of
https://github.com/facebook/react.git
synced 2026-02-26 07:25:30 +00:00
Don't try to hydrate a hidden Offscreen tree (#32862)
I found a bug even before the Activity hydration stuff.
If we're hydrating an Offscreen boundary in its "hidden" state it won't
have any content to hydrate so will trigger hydration errors (which are
then eaten by the Offscreen boundary itself). Leaving it not prewarmed.
This doesn't happen in the simple case because we'd be hydrating at a
higher priority than Offscreen at the root, and those are deferred to
Offscreen by not having higher priority. However, we've hydrating at the
Offscreen priority, which we do inside Suspense boundaries, then it
tries to hydrate against an empty set.
I ended up moving this to the Activity boundary in a future PR since
it's the SSR side that decided where to not render something and it only
has a concept of Activity, no Offscreen.
1dc05a5e22 (diff-d5166797ebbc5b646a49e6a06a049330ca617985d7a6edf3ad1641b43fde1ddfR1111)
This commit is contained in:
committed by
GitHub
parent
539bbdbd86
commit
b04254fdce
@@ -3723,6 +3723,11 @@ describe('ReactDOMServerPartialHydration', () => {
|
||||
<Activity mode="hidden">
|
||||
<HiddenChild />
|
||||
</Activity>
|
||||
<Suspense fallback={null}>
|
||||
<Activity mode="hidden">
|
||||
<HiddenChild />
|
||||
</Activity>
|
||||
</Suspense>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -3743,6 +3748,10 @@ describe('ReactDOMServerPartialHydration', () => {
|
||||
</span>
|
||||
<!--&-->
|
||||
<!--/&-->
|
||||
<!--$-->
|
||||
<!--&-->
|
||||
<!--/&-->
|
||||
<!--/$-->
|
||||
</div>
|
||||
`);
|
||||
|
||||
@@ -3758,6 +3767,7 @@ describe('ReactDOMServerPartialHydration', () => {
|
||||
await waitForPaint([]);
|
||||
}
|
||||
// Subsequently, the hidden child is prerendered on the client
|
||||
// along with hydrating the Suspense boundary outside the Activity.
|
||||
await waitForPaint(['HiddenChild']);
|
||||
expect(container).toMatchInlineSnapshot(`
|
||||
<div>
|
||||
@@ -3766,6 +3776,37 @@ describe('ReactDOMServerPartialHydration', () => {
|
||||
</span>
|
||||
<!--&-->
|
||||
<!--/&-->
|
||||
<!--$-->
|
||||
<!--&-->
|
||||
<!--/&-->
|
||||
<!--/$-->
|
||||
<span
|
||||
style="display: none;"
|
||||
>
|
||||
Hidden
|
||||
</span>
|
||||
</div>
|
||||
`);
|
||||
|
||||
// Next the child inside the Activity is hydrated.
|
||||
await waitForPaint(['HiddenChild']);
|
||||
|
||||
expect(container).toMatchInlineSnapshot(`
|
||||
<div>
|
||||
<span>
|
||||
Visible
|
||||
</span>
|
||||
<!--&-->
|
||||
<!--/&-->
|
||||
<!--$-->
|
||||
<!--&-->
|
||||
<!--/&-->
|
||||
<!--/$-->
|
||||
<span
|
||||
style="display: none;"
|
||||
>
|
||||
Hidden
|
||||
</span>
|
||||
<span
|
||||
style="display: none;"
|
||||
>
|
||||
|
||||
@@ -712,7 +712,14 @@ function updateOffscreenComponent(
|
||||
}
|
||||
reuseHiddenContextOnStack(workInProgress);
|
||||
pushOffscreenSuspenseHandler(workInProgress);
|
||||
} else if (!includesSomeLane(renderLanes, (OffscreenLane: Lane))) {
|
||||
} else if (
|
||||
!includesSomeLane(renderLanes, (OffscreenLane: Lane)) ||
|
||||
// SSR doesn't render hidden content (except legacy hidden) so it shouldn't hydrate,
|
||||
// even at offscreen lane. Defer to a client rendered offscreen lane.
|
||||
(getIsHydrating() &&
|
||||
(!enableLegacyHidden ||
|
||||
nextProps.mode !== 'unstable-defer-without-hiding'))
|
||||
) {
|
||||
// We're hidden, and we're not rendering at Offscreen. We will bail out
|
||||
// and resume this tree later.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user