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 95a414fd9ef7..3b39c83cad17 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 @@ -18,8 +18,9 @@ import type {HostInstance} from 'react-native'; import ensureInstance from '../../../../src/private/__tests__/utilities/ensureInstance'; import * as Fantom from '@react-native/fantom'; +import nullthrows from 'nullthrows'; import * as React from 'react'; -import {Modal, ScrollView, View} from 'react-native'; +import {FlatList, Modal, ScrollView, View} from 'react-native'; import ReactNativeElement from 'react-native/src/private/webapis/dom/nodes/ReactNativeElement'; test('basic culling', () => { @@ -818,6 +819,56 @@ test('culling inside of Modal', () => { ]); }); +test('nesting inside FlatList with item resizing', () => { + const root = Fantom.createRoot({viewportHeight: 100, viewportWidth: 100}); + let _setIsExpanded = null; + function ExpandableComponent() { + const [isExpanded, setIsExpanded] = React.useState(false); + _setIsExpanded = setIsExpanded; + return {isExpanded && }; + } + + Fantom.runTask(() => { + root.render( + { + if (item.key === 'one') { + return ; + } else if (item.key === 'two') { + return ( + // position: 'absolute' is the important part that prevents Yoga from overcloning. + // When Yoga overclones, differentiator visits all cloned nodes and culling is correctly + // applied. + + + + + + ); + } + }} + />, + ); + }); + + expect(root.takeMountingManagerLogs()).toContain( + 'Create {type: "View", nativeID: "child"}', + ); + + Fantom.runTask(() => { + nullthrows(_setIsExpanded)(true); + }); + + expect(root.takeMountingManagerLogs()).toContain( + 'Delete {type: "View", nativeID: "child"}', + ); +}); + describe('reparenting', () => { test('view flattening with culling', () => { const root = Fantom.createRoot({viewportWidth: 100, viewportHeight: 100}); diff --git a/packages/react-native/ReactCommon/react/renderer/mounting/Differentiator.cpp b/packages/react-native/ReactCommon/react/renderer/mounting/Differentiator.cpp index 6dc39b70e749..acd3c7073c3d 100644 --- a/packages/react-native/ReactCommon/react/renderer/mounting/Differentiator.cpp +++ b/packages/react-native/ReactCommon/react/renderer/mounting/Differentiator.cpp @@ -280,7 +280,6 @@ static void updateMatchedPairSubtrees( return; } - // TODO(T217775046): find a test case for this branch. auto oldCullingContextCopy = oldCullingContext.adjustCullingContextIfNeeded(oldPair); auto newCullingContextCopy =