From 815c79e9d46ba08b2531feb74364b3b36f3c4c91 Mon Sep 17 00:00:00 2001 From: Nick Date: Wed, 5 Mar 2025 04:26:10 +0100 Subject: [PATCH 1/4] Disable passChildrenWhenCloning on visibility change --- .../src/ReactFiberCompleteWork.js | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/packages/react-reconciler/src/ReactFiberCompleteWork.js b/packages/react-reconciler/src/ReactFiberCompleteWork.js index 89012e78cf652..979ea8281d0e5 100644 --- a/packages/react-reconciler/src/ReactFiberCompleteWork.js +++ b/packages/react-reconciler/src/ReactFiberCompleteWork.js @@ -342,6 +342,7 @@ function appendAllChildrenToContainer( needsVisibilityToggle: boolean, isHidden: boolean, ) { + let hasOffscreenComponentChild = false; if (supportsPersistence) { // We only have the top Fiber that was created but we need recurse down its // children to find all the terminal nodes. @@ -386,6 +387,8 @@ function appendAllChildrenToContainer( /* needsVisibilityToggle */ _needsVisibilityToggle, /* isHidden */ true, ); + + hasOffscreenComponentChild = true; } else if (node.child !== null) { node.child.return = node; node = node.child; @@ -393,13 +396,13 @@ function appendAllChildrenToContainer( } node = (node: Fiber); if (node === workInProgress) { - return; + return hasOffscreenComponentChild; } // $FlowFixMe[incompatible-use] found when upgrading Flow while (node.sibling === null) { // $FlowFixMe[incompatible-use] found when upgrading Flow if (node.return === null || node.return === workInProgress) { - return; + return hasOffscreenComponentChild; } node = node.return; } @@ -408,6 +411,8 @@ function appendAllChildrenToContainer( node = node.sibling; } } + + return hasOffscreenComponentChild; } function updateHostContainer(current: null | Fiber, workInProgress: Fiber) { @@ -468,11 +473,12 @@ function updateHostComponent( const currentHostContext = getHostContext(); let newChildSet = null; + let hasOffscreenComponentChild = false; if (requiresClone && passChildrenWhenCloningPersistedNodes) { markCloned(workInProgress); newChildSet = createContainerChildSet(); // If children might have changed, we have to add them all to the set. - appendAllChildrenToContainer( + hasOffscreenComponentChild = appendAllChildrenToContainer( newChildSet, workInProgress, /* needsVisibilityToggle */ false, @@ -486,7 +492,7 @@ function updateHostComponent( oldProps, newProps, !requiresClone, - newChildSet, + !hasOffscreenComponentChild ? newChildSet : undefined, ); if (newInstance === currentInstance) { // No changes, just reuse the existing instance. @@ -513,7 +519,7 @@ function updateHostComponent( // Otherwise parents won't know that there are new children to propagate upwards. markUpdate(workInProgress); } - } else if (!passChildrenWhenCloningPersistedNodes) { + } else if (!passChildrenWhenCloningPersistedNodes || hasOffscreenComponentChild) { // If children have changed, we have to add them all to the set. appendAllChildren( newInstance, From f302cc71227299a1e478deaeb279d2d666914e9e Mon Sep 17 00:00:00 2001 From: Nick Date: Wed, 5 Mar 2025 17:54:14 +0100 Subject: [PATCH 2/4] Fix flow type for appendAllChildrenToContainer --- packages/react-reconciler/src/ReactFiberCompleteWork.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/react-reconciler/src/ReactFiberCompleteWork.js b/packages/react-reconciler/src/ReactFiberCompleteWork.js index 979ea8281d0e5..754d878df07ec 100644 --- a/packages/react-reconciler/src/ReactFiberCompleteWork.js +++ b/packages/react-reconciler/src/ReactFiberCompleteWork.js @@ -341,7 +341,7 @@ function appendAllChildrenToContainer( workInProgress: Fiber, needsVisibilityToggle: boolean, isHidden: boolean, -) { +): boolean { let hasOffscreenComponentChild = false; if (supportsPersistence) { // We only have the top Fiber that was created but we need recurse down its From 6b38ca221163f78a157feed686695f1014b6c01e Mon Sep 17 00:00:00 2001 From: Nick Date: Wed, 5 Mar 2025 18:01:29 +0100 Subject: [PATCH 3/4] Run prettier-all --- packages/react-reconciler/src/ReactFiberCompleteWork.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/react-reconciler/src/ReactFiberCompleteWork.js b/packages/react-reconciler/src/ReactFiberCompleteWork.js index 754d878df07ec..c5bd35a3b494f 100644 --- a/packages/react-reconciler/src/ReactFiberCompleteWork.js +++ b/packages/react-reconciler/src/ReactFiberCompleteWork.js @@ -519,7 +519,10 @@ function updateHostComponent( // Otherwise parents won't know that there are new children to propagate upwards. markUpdate(workInProgress); } - } else if (!passChildrenWhenCloningPersistedNodes || hasOffscreenComponentChild) { + } else if ( + !passChildrenWhenCloningPersistedNodes || + hasOffscreenComponentChild + ) { // If children have changed, we have to add them all to the set. appendAllChildren( newInstance, From eb4490e86a412a9c0c558c4dd7481b425c24ed85 Mon Sep 17 00:00:00 2001 From: Nick Date: Thu, 6 Mar 2025 22:38:08 +0100 Subject: [PATCH 4/4] Add comment for offscreen child tracking --- packages/react-reconciler/src/ReactFiberCompleteWork.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/react-reconciler/src/ReactFiberCompleteWork.js b/packages/react-reconciler/src/ReactFiberCompleteWork.js index c5bd35a3b494f..27e4b68134b08 100644 --- a/packages/react-reconciler/src/ReactFiberCompleteWork.js +++ b/packages/react-reconciler/src/ReactFiberCompleteWork.js @@ -342,6 +342,10 @@ function appendAllChildrenToContainer( needsVisibilityToggle: boolean, isHidden: boolean, ): boolean { + // Host components that have their visibility toggled by an OffscreenComponent + // do not support passChildrenWhenCloningPersistedNodes. To inform the callee + // about their presence, we track and return if they were added to the + // child set. let hasOffscreenComponentChild = false; if (supportsPersistence) { // We only have the top Fiber that was created but we need recurse down its