Repository navigation
Conversation
An interior spacer whose first cell is unmeasured started at averageCellLength * index instead of where the rendered cell before it ends. After a large prepend under maintainVisibleContentPosition, the cells after it then moved each time a cell mounted or unmounted at the render window's leading edge, and the list oscillated indefinitely. Fixes react#58870. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2 of 3 tasks
This was referenced Oct 7, 2026
Open
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary:
After a large prepend under
maintainVisibleContentPosition, the spacer between the cells kept byinitialNumToRenderand the render window starts ataverageCellLength * firstrather than where the kept cells end. The cells after it then move each time a cell mounts or unmounts at the window's leading edge, and mVCP's correction moves that edge back, so the content height and offset swing by ~400pt about 15 times a second, indefinitely. This starts a spacer whose first cell is unmeasured where the rendered cell before it ends; only the start is anchored, because sizing it from the cell after it as well would include anygap/rowGaporCellRendererComponentmargins and grow by twice that on every render.Fixes #58870. Repro: https://github.com/mozzius/virtualizedlist-spacer-ring-repro
Changelog:
[GENERAL] [FIXED] - VirtualizedList: anchor an interior spacer's start to the rendered cell before it, so maintainVisibleContentPosition doesn't oscillate after a large prepend
Test Plan:
New test in
VirtualizedList-test.js, with and without a 10pt gap between cells: fails onmain(spacer 1166.7 / 1176.7, expected 1000) and passes with the fix.yarn jest packages/virtualized-lists: 187 passed, all 69 snapshots unchanged.yarn flow-check, eslint and prettier are clean.The repro on an iPhone 17 Pro simulator (iOS 26.5, RN 0.87.1), 4 identical runs per row. Offset jumps the list made by itself after the prepend / while scrolling up in 50pt steps / in 5s at rest:
gap: 10Scrolling 3000pt up through the prepended rows: stock 121 jumps with 109 reversals, the fix 2 with none, with or without the gap. Sizing the spacer from both neighbours instead made 21 jumps of exactly +20pt (twice the gap).
🤖 Generated with Claude Code