diff --git a/packages/react-native/Libraries/Components/ScrollView/__tests__/ScrollView-viewCulling-itest.js b/packages/react-native/Libraries/Components/ScrollView/__tests__/ScrollView-viewCulling-itest.js
index fdfbc7b0bc72..bec55546a9e7 100644
--- a/packages/react-native/Libraries/Components/ScrollView/__tests__/ScrollView-viewCulling-itest.js
+++ b/packages/react-native/Libraries/Components/ScrollView/__tests__/ScrollView-viewCulling-itest.js
@@ -1315,3 +1315,156 @@ test('parent-child switching from unflattened-flattened to flattened-unflattened
'Insert {type: "View", parentNativeID: (N/A), index: 0, nativeID: (N/A)}',
]);
});
+
+test('unflattening and creating a subtree that is partially culled', () => {
+ const root = Fantom.createRoot({viewportWidth: 100, viewportHeight: 100});
+
+ // First render with a flattened view container that is visible.
+ Fantom.runTask(() => {
+ root.render(
+
+
+ ,
+ );
+ });
+
+ expect(root.takeMountingManagerLogs()).toEqual([
+ 'Update {type: "RootView", nativeID: (root)}',
+ 'Create {type: "ScrollView", nativeID: (N/A)}',
+ 'Create {type: "View", nativeID: (N/A)}',
+ 'Insert {type: "View", parentNativeID: (N/A), index: 0, nativeID: (N/A)}',
+ 'Insert {type: "ScrollView", parentNativeID: (root), index: 0, nativeID: (N/A)}',
+ ]);
+
+ let maybeNode = null;
+
+ // Now update opacity to unflattned the container and add a child that has a culled descendant.
+ Fantom.runTask(() => {
+ root.render(
+ {
+ maybeNode = node;
+ }}
+ contentOffset={{x: 0, y: 111}}>
+
+
+
+
+
+ ,
+ );
+ });
+
+ expect(root.takeMountingManagerLogs()).toEqual([
+ 'Update {type: "ScrollView", nativeID: (N/A)}',
+ 'Update {type: "View", nativeID: (N/A)}',
+ 'Create {type: "View", nativeID: (N/A)}',
+ 'Create {type: "View", nativeID: "child"}',
+ 'Insert {type: "View", parentNativeID: (N/A), index: 0, nativeID: (N/A)}',
+ 'Insert {type: "View", parentNativeID: (N/A), index: 0, nativeID: "child"}',
+ ]);
+
+ const element = ensureInstance(maybeNode, ReactNativeElement);
+
+ // Scroll down to see the grandchild.
+ Fantom.scrollTo(element, {
+ x: 0,
+ y: 115,
+ });
+
+ expect(root.takeMountingManagerLogs()).toEqual([
+ 'Update {type: "ScrollView", nativeID: (N/A)}',
+ 'Create {type: "View", nativeID: "grandchild"}',
+ 'Insert {type: "View", parentNativeID: "child", index: 0, nativeID: "grandchild"}',
+ ]);
+});
+
+test('flattening and deleting a subtree that is partially culled', () => {
+ const root = Fantom.createRoot({viewportWidth: 100, viewportHeight: 100});
+
+ // First render with a unflattened view container that is visible and a subtree that is partially culled.
+ Fantom.runTask(() => {
+ root.render(
+
+
+
+
+
+
+ ,
+ );
+ });
+
+ // All views are mounted, except for the grandchild.
+ expect(root.takeMountingManagerLogs()).toEqual([
+ 'Update {type: "RootView", nativeID: (root)}',
+ 'Create {type: "ScrollView", nativeID: (N/A)}',
+ 'Create {type: "View", nativeID: (N/A)}',
+ 'Create {type: "View", nativeID: (N/A)}',
+ 'Create {type: "View", nativeID: "child"}',
+ 'Insert {type: "View", parentNativeID: (N/A), index: 0, nativeID: "child"}',
+ 'Insert {type: "View", parentNativeID: (N/A), index: 0, nativeID: (N/A)}',
+ 'Insert {type: "View", parentNativeID: (N/A), index: 0, nativeID: (N/A)}',
+ 'Insert {type: "ScrollView", parentNativeID: (root), index: 0, nativeID: (N/A)}',
+ ]);
+
+ // Now change opacity to the default to flatten the container and delete container's subtree.
+ Fantom.runTask(() => {
+ root.render(
+
+
+ ,
+ );
+ });
+
+ // Note that the grandchild is not deleted because it was not previously mounted.
+ expect(root.takeMountingManagerLogs()).toEqual([
+ 'Update {type: "ScrollView", nativeID: (N/A)}',
+ 'Update {type: "View", nativeID: (N/A)}',
+ 'Remove {type: "View", parentNativeID: (N/A), index: 0, nativeID: "child"}',
+ 'Remove {type: "View", parentNativeID: (N/A), index: 0, nativeID: (N/A)}',
+ 'Delete {type: "View", nativeID: (N/A)}',
+ 'Delete {type: "View", nativeID: "child"}',
+ ]);
+});
diff --git a/packages/react-native/ReactCommon/react/renderer/mounting/Differentiator.cpp b/packages/react-native/ReactCommon/react/renderer/mounting/Differentiator.cpp
index a7c6307c2cca..e6b86171c79f 100644
--- a/packages/react-native/ReactCommon/react/renderer/mounting/Differentiator.cpp
+++ b/packages/react-native/ReactCommon/react/renderer/mounting/Differentiator.cpp
@@ -854,8 +854,6 @@ static void calculateShadowViewMutationsFlattener(
if (!treeChildPair.flattened) {
ViewNodePairScope innerScope{};
- // TODO(T217775046): Find a test case for this branch of view
- // flattening + culling.
calculateShadowViewMutations(
innerScope,
mutationContainer.destructiveDownwardMutations,
@@ -872,8 +870,6 @@ static void calculateShadowViewMutationsFlattener(
if (!treeChildPair.flattened) {
ViewNodePairScope innerScope{};
- // TODO(T217775046): Find a test case for this branch of view
- // flattening + culling.
calculateShadowViewMutations(
innerScope,
mutationContainer.downwardMutations,