Skip to content

Commit b76acc3

Browse files
committed
[Fabric] Fix reparenting in legacy Suspense mount
Fixes a weird case during legacy Suspense mount where the offscreen host container of a tree that suspends during initial mount is recreated instead of cloned, since there's no current fiber to clone from. Fabric considers this a reparent even though the parent from the first pass never committed. Instead we can override the props from the first pass before the container completes. It's a bit of a hack, but no more so than the rest of the legacy root Suspense implementation — the hacks are designed to make it usable by non-strict mode-compliant trees.
1 parent 7addf44 commit b76acc3

File tree

4 files changed

+48
-30
lines changed

4 files changed

+48
-30
lines changed

packages/react-reconciler/src/ReactFiberBeginWork.new.js

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2212,21 +2212,6 @@ function mountSuspenseFallbackChildren(
22122212
primaryChildFragment.childLanes = NoLanes;
22132213
primaryChildFragment.pendingProps = primaryChildProps;
22142214

2215-
if (
2216-
supportsPersistence &&
2217-
(workInProgress.mode & ConcurrentMode) === NoMode
2218-
) {
2219-
const isHidden = true;
2220-
const offscreenContainer: Fiber = (primaryChildFragment.child: any);
2221-
const containerProps = {
2222-
hidden: isHidden,
2223-
primaryChildren,
2224-
};
2225-
offscreenContainer.pendingProps = containerProps;
2226-
offscreenContainer.memoizedProps = containerProps;
2227-
completeSuspendedOffscreenHostContainer(null, offscreenContainer);
2228-
}
2229-
22302215
if (enableProfilerTimer && workInProgress.mode & ProfileMode) {
22312216
// Reset the durations from the first pass so they aren't included in the
22322217
// final amounts. This seems counterintuitive, since we're intentionally

packages/react-reconciler/src/ReactFiberBeginWork.old.js

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2212,21 +2212,6 @@ function mountSuspenseFallbackChildren(
22122212
primaryChildFragment.childLanes = NoLanes;
22132213
primaryChildFragment.pendingProps = primaryChildProps;
22142214

2215-
if (
2216-
supportsPersistence &&
2217-
(workInProgress.mode & ConcurrentMode) === NoMode
2218-
) {
2219-
const isHidden = true;
2220-
const offscreenContainer: Fiber = (primaryChildFragment.child: any);
2221-
const containerProps = {
2222-
hidden: isHidden,
2223-
primaryChildren,
2224-
};
2225-
offscreenContainer.pendingProps = containerProps;
2226-
offscreenContainer.memoizedProps = containerProps;
2227-
completeSuspendedOffscreenHostContainer(null, offscreenContainer);
2228-
}
2229-
22302215
if (enableProfilerTimer && workInProgress.mode & ProfileMode) {
22312216
// Reset the durations from the first pass so they aren't included in the
22322217
// final amounts. This seems counterintuitive, since we're intentionally

packages/react-reconciler/src/ReactFiberThrow.new.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@ import {
3333
LifecycleEffectMask,
3434
ForceUpdateForLegacySuspense,
3535
} from './ReactFiberFlags';
36+
import {
37+
supportsPersistence,
38+
getOffscreenContainerProps,
39+
} from './ReactFiberHostConfig';
3640
import {shouldCaptureSuspense} from './ReactFiberSuspenseComponent.new';
3741
import {NoMode, ConcurrentMode, DebugTracingMode} from './ReactTypeOfMode';
3842
import {
@@ -313,6 +317,26 @@ function throwException(
313317
// all lifecycle effect tags.
314318
sourceFiber.flags &= ~(LifecycleEffectMask | Incomplete);
315319

320+
if (supportsPersistence) {
321+
// Another legacy Suspense quirk. In persistent mode, if this is the
322+
// initial mount, override the props of the host container to hide
323+
// its contents.
324+
const currentSuspenseBoundary = workInProgress.alternate;
325+
if (currentSuspenseBoundary === null) {
326+
const offscreenFiber: Fiber = (workInProgress.child: any);
327+
const offscreenContainer = offscreenFiber.child;
328+
if (offscreenContainer !== null) {
329+
const children = offscreenContainer.memoizedProps.children;
330+
const containerProps = getOffscreenContainerProps(
331+
'hidden',
332+
children,
333+
);
334+
offscreenContainer.pendingProps = containerProps;
335+
offscreenContainer.memoizedProps = containerProps;
336+
}
337+
}
338+
}
339+
316340
if (sourceFiber.tag === ClassComponent) {
317341
const currentSourceFiber = sourceFiber.alternate;
318342
if (currentSourceFiber === null) {

packages/react-reconciler/src/ReactFiberThrow.old.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@ import {
3333
LifecycleEffectMask,
3434
ForceUpdateForLegacySuspense,
3535
} from './ReactFiberFlags';
36+
import {
37+
supportsPersistence,
38+
getOffscreenContainerProps,
39+
} from './ReactFiberHostConfig';
3640
import {shouldCaptureSuspense} from './ReactFiberSuspenseComponent.old';
3741
import {NoMode, ConcurrentMode, DebugTracingMode} from './ReactTypeOfMode';
3842
import {
@@ -313,6 +317,26 @@ function throwException(
313317
// all lifecycle effect tags.
314318
sourceFiber.flags &= ~(LifecycleEffectMask | Incomplete);
315319

320+
if (supportsPersistence) {
321+
// Another legacy Suspense quirk. In persistent mode, if this is the
322+
// initial mount, override the props of the host container to hide
323+
// its contents.
324+
const currentSuspenseBoundary = workInProgress.alternate;
325+
if (currentSuspenseBoundary === null) {
326+
const offscreenFiber: Fiber = (workInProgress.child: any);
327+
const offscreenContainer = offscreenFiber.child;
328+
if (offscreenContainer !== null) {
329+
const children = offscreenContainer.memoizedProps.children;
330+
const containerProps = getOffscreenContainerProps(
331+
'hidden',
332+
children,
333+
);
334+
offscreenContainer.pendingProps = containerProps;
335+
offscreenContainer.memoizedProps = containerProps;
336+
}
337+
}
338+
}
339+
316340
if (sourceFiber.tag === ClassComponent) {
317341
const currentSourceFiber = sourceFiber.alternate;
318342
if (currentSourceFiber === null) {

0 commit comments

Comments
 (0)