diff --git a/packages/react-reconciler/src/ReactFiberCommitWork.new.js b/packages/react-reconciler/src/ReactFiberCommitWork.new.js
index a68e489dccc98..f9d9ad39999f5 100644
--- a/packages/react-reconciler/src/ReactFiberCommitWork.new.js
+++ b/packages/react-reconciler/src/ReactFiberCommitWork.new.js
@@ -2131,8 +2131,7 @@ function commitMutationEffectsOnFiber(finishedWork: Fiber, root: FiberRoot) {
}
break;
}
- case OffscreenComponent:
- case LegacyHiddenComponent: {
+ case OffscreenComponent: {
const newState: OffscreenState | null = finishedWork.memoizedState;
const isHidden = newState !== null;
const current = finishedWork.alternate;
@@ -2145,27 +2144,26 @@ function commitMutationEffectsOnFiber(finishedWork: Fiber, root: FiberRoot) {
hideOrUnhideAllChildren(offscreenBoundary, isHidden);
}
- if (isHidden) {
- if (!wasHidden) {
- if (
- enableSuspenseLayoutEffectSemantics &&
- (offscreenBoundary.mode & ConcurrentMode) !== NoMode
- ) {
- nextEffect = offscreenBoundary;
- let offscreenChild = offscreenBoundary.child;
- while (offscreenChild !== null) {
- nextEffect = offscreenChild;
- disappearLayoutEffects_begin(offscreenChild);
- offscreenChild = offscreenChild.sibling;
+ if (enableSuspenseLayoutEffectSemantics) {
+ if (isHidden) {
+ if (!wasHidden) {
+ if ((offscreenBoundary.mode & ConcurrentMode) !== NoMode) {
+ nextEffect = offscreenBoundary;
+ let offscreenChild = offscreenBoundary.child;
+ while (offscreenChild !== null) {
+ nextEffect = offscreenChild;
+ disappearLayoutEffects_begin(offscreenChild);
+ offscreenChild = offscreenChild.sibling;
+ }
}
}
+ } else {
+ if (wasHidden) {
+ // TODO: Move re-appear call here for symmetry?
+ }
}
- } else {
- if (wasHidden) {
- // TODO: Move re-appear call here for symmetry?
- }
+ break;
}
- break;
}
}
}
diff --git a/packages/react-reconciler/src/ReactFiberCommitWork.old.js b/packages/react-reconciler/src/ReactFiberCommitWork.old.js
index aea3e36ed09d2..60c230cd251be 100644
--- a/packages/react-reconciler/src/ReactFiberCommitWork.old.js
+++ b/packages/react-reconciler/src/ReactFiberCommitWork.old.js
@@ -2131,8 +2131,7 @@ function commitMutationEffectsOnFiber(finishedWork: Fiber, root: FiberRoot) {
}
break;
}
- case OffscreenComponent:
- case LegacyHiddenComponent: {
+ case OffscreenComponent: {
const newState: OffscreenState | null = finishedWork.memoizedState;
const isHidden = newState !== null;
const current = finishedWork.alternate;
@@ -2145,27 +2144,26 @@ function commitMutationEffectsOnFiber(finishedWork: Fiber, root: FiberRoot) {
hideOrUnhideAllChildren(offscreenBoundary, isHidden);
}
- if (isHidden) {
- if (!wasHidden) {
- if (
- enableSuspenseLayoutEffectSemantics &&
- (offscreenBoundary.mode & ConcurrentMode) !== NoMode
- ) {
- nextEffect = offscreenBoundary;
- let offscreenChild = offscreenBoundary.child;
- while (offscreenChild !== null) {
- nextEffect = offscreenChild;
- disappearLayoutEffects_begin(offscreenChild);
- offscreenChild = offscreenChild.sibling;
+ if (enableSuspenseLayoutEffectSemantics) {
+ if (isHidden) {
+ if (!wasHidden) {
+ if ((offscreenBoundary.mode & ConcurrentMode) !== NoMode) {
+ nextEffect = offscreenBoundary;
+ let offscreenChild = offscreenBoundary.child;
+ while (offscreenChild !== null) {
+ nextEffect = offscreenChild;
+ disappearLayoutEffects_begin(offscreenChild);
+ offscreenChild = offscreenChild.sibling;
+ }
}
}
+ } else {
+ if (wasHidden) {
+ // TODO: Move re-appear call here for symmetry?
+ }
}
- } else {
- if (wasHidden) {
- // TODO: Move re-appear call here for symmetry?
- }
+ break;
}
- break;
}
}
}
diff --git a/packages/react-reconciler/src/ReactFiberCompleteWork.new.js b/packages/react-reconciler/src/ReactFiberCompleteWork.new.js
index 32b9587f26314..b6feee098b4f4 100644
--- a/packages/react-reconciler/src/ReactFiberCompleteWork.new.js
+++ b/packages/react-reconciler/src/ReactFiberCompleteWork.new.js
@@ -1361,7 +1361,9 @@ function completeWork(
const prevIsHidden = prevState !== null;
if (
prevIsHidden !== nextIsHidden &&
- newProps.mode !== 'unstable-defer-without-hiding'
+ newProps.mode !== 'unstable-defer-without-hiding' &&
+ // LegacyHidden doesn't do any hiding — it only pre-renders.
+ workInProgress.tag !== LegacyHiddenComponent
) {
workInProgress.flags |= Visibility;
}
diff --git a/packages/react-reconciler/src/ReactFiberCompleteWork.old.js b/packages/react-reconciler/src/ReactFiberCompleteWork.old.js
index 60359fd42d8de..612ad2db52c9f 100644
--- a/packages/react-reconciler/src/ReactFiberCompleteWork.old.js
+++ b/packages/react-reconciler/src/ReactFiberCompleteWork.old.js
@@ -1361,7 +1361,9 @@ function completeWork(
const prevIsHidden = prevState !== null;
if (
prevIsHidden !== nextIsHidden &&
- newProps.mode !== 'unstable-defer-without-hiding'
+ newProps.mode !== 'unstable-defer-without-hiding' &&
+ // LegacyHidden doesn't do any hiding — it only pre-renders.
+ workInProgress.tag !== LegacyHiddenComponent
) {
workInProgress.flags |= Visibility;
}
diff --git a/packages/react-reconciler/src/__tests__/ReactOffscreen-test.js b/packages/react-reconciler/src/__tests__/ReactOffscreen-test.js
index 2915b1e769f04..9f9225fea3bad 100644
--- a/packages/react-reconciler/src/__tests__/ReactOffscreen-test.js
+++ b/packages/react-reconciler/src/__tests__/ReactOffscreen-test.js
@@ -337,4 +337,52 @@ describe('ReactOffscreen', () => {
expect(root).toMatchRenderedOutput();
}
});
+
+ // @gate experimental || www
+ it('does not toggle effects for LegacyHidden component', async () => {
+ // LegacyHidden is meant to be the same as offscreen except it doesn't
+ // do anything to effects. Only used by www, as a temporary migration step.
+ function Child({text}) {
+ useLayoutEffect(() => {
+ Scheduler.unstable_yieldValue('Mount layout');
+ return () => {
+ Scheduler.unstable_yieldValue('Unmount layout');
+ };
+ }, []);
+ return ;
+ }
+
+ const root = ReactNoop.createRoot();
+ await act(async () => {
+ root.render(
+
+
+ ,
+ );
+ });
+ expect(Scheduler).toHaveYielded(['Child', 'Mount layout']);
+
+ await act(async () => {
+ root.render(
+
+
+ ,
+ );
+ });
+ expect(Scheduler).toHaveYielded(['Child']);
+
+ await act(async () => {
+ root.render(
+
+
+ ,
+ );
+ });
+ expect(Scheduler).toHaveYielded(['Child']);
+
+ await act(async () => {
+ root.render(null);
+ });
+ expect(Scheduler).toHaveYielded(['Unmount layout']);
+ });
});