Skip to content

Use the sticky wrapper's layout for sticky header cells (#59199) - #59199

Open
ramya-2196 wants to merge 1 commit into
react:mainfrom
ramya-2196:export-D126073361
Open

ramya-2196 wants to merge 1 commit into
react:mainfrom
ramya-2196:export-D126073361

Conversation

@ramya-2196

@ramya-2196 ramya-2196 commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor

Summary:

What

VirtualizedList now records the position of a sticky header cell from its sticky wrapper, instead of from the cell's own layout. This affects FlatList with stickyHeaderIndices and SectionList with sticky section headers. JS only; no new props or public API.

  • VirtualizedList.js: sticky cells get an onLayout callback, and that layout takes priority over the cell's own onCellLayout measurement.
  • VirtualizedListCellRenderer.js: adds the optional onLayout prop type.
  • VirtualizedList.macos.js, VirtualizedList.windows.js, VirtualizedListCellRenderer.macos.js: the same change.

Why

Fixes part of #37439. With sticky headers, onViewableItemsChanged never reports the next sticky header or any item after it, even when they are fully on screen.

ScrollView wraps every sticky child in ScrollViewStickyHeader. The cell's inner View therefore measures its layout relative to that wrapper, so a sticky cell's offset is always about 0 instead of its position in the list. Viewability scans cells in order and stops at the first cell that is not visible after a visible one. A sticky header stored at offset 0 looks scrolled off the top, so the scan stops there and drops it and everything after it.

Example: groups of one 50px header and five 80px rows, scrolled to y=254 with header A pinned. Header B (at 450) and B1-B4 are on screen, but only A4, A5 are reported.

How

ScrollViewStickyHeader already calls the child element's onLayout with the wrapper's layout, which is relative to the list content. Since cells moved their layout callback to onCellLayout, nothing received it. VirtualizedList now passes onLayout to sticky cells and records that layout.

The cell's own measurement is still recorded until the wrapper reports, so a custom StickyHeaderComponent that does not forward onLayout behaves exactly as before. Once the wrapper has reported, later inner measurements for that cell are ignored. The flag is cleared when the cell unmounts or stops being sticky.

Alternative considered: changing ScrollViewStickyHeader to forward onCellLayout as well. Rejected because it would teach ScrollView about a list-specific prop.

For Reviewers

Changelog:
[General][Fixed] - Fix onViewableItemsChanged skipping the next sticky header and the items after it in FlatList and SectionList

Differential Revision: D126073361

@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Oct 19, 2026
@meta-codesync

meta-codesync Bot commented Oct 19, 2026

Copy link
Copy Markdown

@ramya-2196 has exported this pull request. If you are a Meta employee, you can view the originating Diff in D126073361.

Summary:

### What

`VirtualizedList` now records the position of a sticky header cell from its sticky wrapper, instead of from the cell's own layout. This affects `FlatList` with `stickyHeaderIndices` and `SectionList` with sticky section headers. JS only; no new props or public API.

- `VirtualizedList.js`: sticky cells get an `onLayout` callback, and that layout takes priority over the cell's own `onCellLayout` measurement.
- `VirtualizedListCellRenderer.js`: adds the optional `onLayout` prop type.
- `VirtualizedList.macos.js`, `VirtualizedList.windows.js`, `VirtualizedListCellRenderer.macos.js`: the same change.

### Why

Fixes part of react#37439. With sticky headers, `onViewableItemsChanged` never reports the next sticky header or any item after it, even when they are fully on screen.

`ScrollView` wraps every sticky child in `ScrollViewStickyHeader`. The cell's inner `View` therefore measures its layout relative to that wrapper, so a sticky cell's offset is always about 0 instead of its position in the list. Viewability scans cells in order and stops at the first cell that is not visible after a visible one. A sticky header stored at offset 0 looks scrolled off the top, so the scan stops there and drops it and everything after it.

Example: groups of one 50px header and five 80px rows, scrolled to y=254 with header A pinned. Header B (at 450) and B1-B4 are on screen, but only `A4, A5` are reported.

### How

`ScrollViewStickyHeader` already calls the child element's `onLayout` with the wrapper's layout, which is relative to the list content. Since cells moved their layout callback to `onCellLayout`, nothing received it. `VirtualizedList` now passes `onLayout` to sticky cells and records that layout.

The cell's own measurement is still recorded until the wrapper reports, so a custom `StickyHeaderComponent` that does not forward `onLayout` behaves exactly as before. Once the wrapper has reported, later inner measurements for that cell are ignored. The flag is cleared when the cell unmounts or stops being sticky.

Alternative considered: changing `ScrollViewStickyHeader` to forward `onCellLayout` as well. Rejected because it would teach `ScrollView` about a list-specific prop.

### For Reviewers

- This does not fix the other half of react#37439: items hidden behind the pinned header are still reported as viewable. That needs a separate change in `ViewabilityHelper`.
- Sticky cell offsets also feed render windowing, `scrollToIndex`, and fill-rate tracking, so those now use the correct positions too.

Changelog:
[General][Fixed] - Fix `onViewableItemsChanged` skipping the next sticky header and the items after it in `FlatList` and `SectionList`

Differential Revision: D126073361
@meta-codesync meta-codesync Bot changed the title Use the sticky wrapper's layout for sticky header cells Use the sticky wrapper's layout for sticky header cells (#59199) Oct 19, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. meta-exported p: Facebook Partner: Facebook Partner

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant