mirror of
https://github.com/react/react-native.git
synced 2026-09-28 05:13:06 +08:00
Summary: `VirtualizedList`/`FlatList`/`SectionList` re-run a small amount of bookkeeping on every render and on every scroll event (60–120 Hz on ProMotion displays). This PR removes three allocations from those hot paths without changing any observable behavior: 1. **`VirtualizedList.render` no longer builds a `Set` for `stickyHeaderIndices` on every render** when the prop is not provided (the common case). The Set is now only created when the prop is present; the two `.has()` lookups use optional access. 2. **`ChildListCollection.forEach` returns early when there are no nested child lists** (the common case) instead of allocating a `Map.values()` iterator. This is called from `_onScroll` and the four other scroll callbacks on every scroll event. 3. **`_orientation()` caches its result** and only rebuilds the object when the `horizontal` prop changes. `I18nManager.isRTL` is a module-load constant (only changes on app reload), so the cache is invalidated solely by the `horizontal` prop. The object is replaced, never mutated, which keeps `ListMetricsAggregator`'s field-based invalidation correct. ## Changelog: [GENERAL][CHANGED] - Reduce allocations in the `VirtualizedList` render and scroll path (avoid per-render `Set` allocation for `stickyHeaderIndices`, per-scroll-event `Map` iterator for the empty nested-list collection, and per-call `orientation` object allocation) Pull Request resolved: https://github.com/react/react-native/pull/58593 Test Plan: - `yarn test packages/virtualized-lists` → 9 suites, 186 passed, 69 snapshots: - `ChildListCollection-test.js` (new): forEach over populated/empty collection, removal, `forEachInCell`/`anyInCell` - `VirtualizedList-test.js`: `stickyHeaderIndices` not forwarded when the prop is absent (with `ListHeaderComponent`), forwarded when provided; orientation cache identity + invalidation on `horizontal` change - `yarn flow-check` → 0 errors - `yarn lint` → 0 errors, 0 warnings - `yarn format-check` (changed files) Micro-benchmark (Node v24, V8, 2M iterations, before vs after, same machine; the real-world benefit is dominated by reduced GC pressure, which is largest on low-end Android): Reviewed By: Abbondanzo Differential Revision: D121177373 Pulled By: javache fbshipit-source-id: 1befd7e6d90fbd1fcea9c4cc8cf6d575c6c26111