Files
Sedat Çiftçi 731ae45ae6 Reduce allocations in VirtualizedList render and scroll path (#58593)
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
2026-09-23 05:15:29 -07:00
..

@react-native/virtualized-lists

npm npm downloads

This is an internal dependency of React Native. Please don't depend on it directly.

Virtualized list primitives (VirtualizedList, VirtualizedSectionList) backing React Native's FlatList and SectionList components.