diff --git a/packages/react-reconciler/src/ReactFiberCommitWork.new.js b/packages/react-reconciler/src/ReactFiberCommitWork.new.js
index 7e489ccfe74ba..e0bd907706f61 100644
--- a/packages/react-reconciler/src/ReactFiberCommitWork.new.js
+++ b/packages/react-reconciler/src/ReactFiberCommitWork.new.js
@@ -52,6 +52,7 @@ import {
enableUseEventHook,
enableStrictEffects,
enableFloat,
+ enableLegacyHidden,
} from 'shared/ReactFeatureFlags';
import {
FunctionComponent,
@@ -3419,7 +3420,23 @@ function commitPassiveMountOnFiber(
}
break;
}
- case LegacyHiddenComponent:
+ case LegacyHiddenComponent: {
+ if (enableLegacyHidden) {
+ recursivelyTraversePassiveMountEffects(
+ finishedRoot,
+ finishedWork,
+ committedLanes,
+ committedTransitions,
+ );
+
+ if (flags & Passive) {
+ const current = finishedWork.alternate;
+ const instance: OffscreenInstance = finishedWork.stateNode;
+ commitOffscreenPassiveMountEffects(current, finishedWork, instance);
+ }
+ }
+ break;
+ }
case OffscreenComponent: {
// TODO: Pass `current` as argument to this function
const instance: OffscreenInstance = finishedWork.stateNode;
@@ -3600,7 +3617,25 @@ export function reconnectPassiveEffects(
// case HostRoot: {
// ...
// }
- case LegacyHiddenComponent:
+ case LegacyHiddenComponent: {
+ if (enableLegacyHidden) {
+ recursivelyTraverseReconnectPassiveEffects(
+ finishedRoot,
+ finishedWork,
+ committedLanes,
+ committedTransitions,
+ includeWorkInProgressEffects,
+ );
+
+ if (includeWorkInProgressEffects && flags & Passive) {
+ // TODO: Pass `current` as argument to this function
+ const current: Fiber | null = finishedWork.alternate;
+ const instance: OffscreenInstance = finishedWork.stateNode;
+ commitOffscreenPassiveMountEffects(current, finishedWork, instance);
+ }
+ }
+ break;
+ }
case OffscreenComponent: {
const instance: OffscreenInstance = finishedWork.stateNode;
const nextState: OffscreenState | null = finishedWork.memoizedState;
diff --git a/packages/react-reconciler/src/ReactFiberCommitWork.old.js b/packages/react-reconciler/src/ReactFiberCommitWork.old.js
index 4957356c30383..0f449a81dc836 100644
--- a/packages/react-reconciler/src/ReactFiberCommitWork.old.js
+++ b/packages/react-reconciler/src/ReactFiberCommitWork.old.js
@@ -52,6 +52,7 @@ import {
enableUseEventHook,
enableStrictEffects,
enableFloat,
+ enableLegacyHidden,
} from 'shared/ReactFeatureFlags';
import {
FunctionComponent,
@@ -3419,7 +3420,23 @@ function commitPassiveMountOnFiber(
}
break;
}
- case LegacyHiddenComponent:
+ case LegacyHiddenComponent: {
+ if (enableLegacyHidden) {
+ recursivelyTraversePassiveMountEffects(
+ finishedRoot,
+ finishedWork,
+ committedLanes,
+ committedTransitions,
+ );
+
+ if (flags & Passive) {
+ const current = finishedWork.alternate;
+ const instance: OffscreenInstance = finishedWork.stateNode;
+ commitOffscreenPassiveMountEffects(current, finishedWork, instance);
+ }
+ }
+ break;
+ }
case OffscreenComponent: {
// TODO: Pass `current` as argument to this function
const instance: OffscreenInstance = finishedWork.stateNode;
@@ -3600,7 +3617,25 @@ export function reconnectPassiveEffects(
// case HostRoot: {
// ...
// }
- case LegacyHiddenComponent:
+ case LegacyHiddenComponent: {
+ if (enableLegacyHidden) {
+ recursivelyTraverseReconnectPassiveEffects(
+ finishedRoot,
+ finishedWork,
+ committedLanes,
+ committedTransitions,
+ includeWorkInProgressEffects,
+ );
+
+ if (includeWorkInProgressEffects && flags & Passive) {
+ // TODO: Pass `current` as argument to this function
+ const current: Fiber | null = finishedWork.alternate;
+ const instance: OffscreenInstance = finishedWork.stateNode;
+ commitOffscreenPassiveMountEffects(current, finishedWork, instance);
+ }
+ }
+ break;
+ }
case OffscreenComponent: {
const instance: OffscreenInstance = finishedWork.stateNode;
const nextState: OffscreenState | null = finishedWork.memoizedState;
diff --git a/packages/react-reconciler/src/__tests__/ReactOffscreen-test.js b/packages/react-reconciler/src/__tests__/ReactOffscreen-test.js
index 30bbaea058995..ca505c785fe48 100644
--- a/packages/react-reconciler/src/__tests__/ReactOffscreen-test.js
+++ b/packages/react-reconciler/src/__tests__/ReactOffscreen-test.js
@@ -942,6 +942,62 @@ describe('ReactOffscreen', () => {
]);
});
+ // @gate enableLegacyHidden
+ it('do not defer passive effects when prerendering a new LegacyHidden tree', async () => {
+ function Child({label}) {
+ useEffect(() => {
+ Scheduler.unstable_yieldValue('Mount ' + label);
+ return () => {
+ Scheduler.unstable_yieldValue('Unmount ' + label);
+ };
+ }, [label]);
+ return ;
+ }
+
+ function App({showMore}) {
+ return (
+ <>
+
+
+
+
+ >
+ );
+ }
+
+ const root = ReactNoop.createRoot();
+
+ // Mount the app without showing the extra content
+ await act(async () => {
+ root.render();
+ });
+ expect(Scheduler).toHaveYielded([
+ // First mount the outer visible shell
+ 'Shell',
+ 'Mount Shell',
+
+ // Then prerender the hidden extra context. Unlike Offscreen, the passive
+ // effects in the hidden tree *should* fire
+ 'More',
+ 'Mount More',
+ ]);
+
+ // The hidden content has been prerendered
+ expect(root).toMatchRenderedOutput(
+ <>
+
+
+ >,
+ );
+
+ // Reveal the prerendered tree
+ await act(async () => {
+ root.render();
+ });
+ expect(Scheduler).toHaveYielded(['Shell', 'More']);
+ });
+
// @gate enableOffscreen
it('passive effects are connected and disconnected when the visibility changes', async () => {
function Child({step}) {