[WEB] Scrollbar oscillation cause infinite layout loop
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 7.2k
- Forks
- 393
- Avg merge
- 1d 3h
- Merged PRs (30d)
- 1
Description
Description
On web with classic (non-overlay) scrollbars — i.e. Windows/Linux Chrome and macOS with "Always show scroll bars", FlashList v2 can enter an infinite layout loop and crash with Maximum update depth exceeded because the vertical scrollbar's own appearance/disappearance feeds back into the list's cross-axis (width) measurement.
When list content height sits right at the threshold where it just barely overflows the viewport, the browser shows a vertical scrollbar. The scrollbar consumes ~15–17px of width, which reduces the measured client width FlashList uses as boundedSize. The narrower width re-flows items so the content no longer overflows → the scrollbar is removed → the measured width grows back → content overflows again → the scrollbar returns → and so on, forever.
This is web-specific: native platforms use overlay scrollbars that don't consume layout width, so they never oscillate.
Current behavior
- The list rapidly re-lays-out, the scrollbar visibly flickers, and React throws
Maximum update depth exceeded(setStateloop inupdateLayoutParams→ recompute layout → measure →updateLayoutParams…), crashing the app. - Happens whenever content size is near the boundary at which adding/removing the scrollbar flips whether the content overflows.
Expected behavior
FlashList should not let the scrollbar's own width feedback-loop the layout.
Reproduction
Expo Snack or minimal reproduction link:
Make sure to test on web with classic (non-overlay) scrollbar. If you use MacOS fo to Settings -> Appearance -> Windows -> Show scroll bars -> Always.
https://snack.expo.dev/@vikstash/flashlist_loop_crash
Platform
- iOS
- Android
- Web (if applicable)
Environment
React Native info output:
Paste output here
FlashList version:
2.3.0
Additional context
Root cause is in LinearLayoutManager.ts, method updateLayoutParams. boundedSize is taken directly from the measured window size with no detection of scrollbar-induced oscillation, so the scrollbar appearing/disappearing keeps changing the measured width and re-triggering layout.
Checklist
- I've searched existing issues and couldn't find a duplicate
- I've provided a minimal reproduction (Expo Snack preferred)
- I'm using the latest version of @shopify/flash-list
- I've included all required information above
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with src/recyclerview/layout-managers/LinearLayoutManager.ts, especially updateLayoutParams and its boundedSize calculation. Reproduce the crash using the linked Expo Snack on web with classic scrollbars, then trace the updateLayoutParams → layout → measure cycle. Done means the scrollbar no longer causes an infinite layout loop or Maximum update depth exceeded error.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- react-native, typescript
- Domain
- frontend, performance
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 68/100