Skip to content

Conversation

@ibrahimhajjaj
Copy link

Summary

Fixes a race condition in VirtualizedList where initialScrollIndex is ignored when a scroll event with offset=0 arrives before the native scroll completes.

The Problem:
When initialScrollIndex > 0 (e.g., 331), a scroll event with offset=0 could arrive before the native scroll completes. This would:

  1. Decrement pendingScrollUpdateCount to 0
  2. Allow _adjustCellsAroundViewport to recalculate the render window using stale scroll metrics (offset=0)
  3. Cause items 0-N to render instead of items around the target initialScrollIndex

The Fix:
Added a guard in _onScroll() to only decrement pendingScrollUpdateCount when:

  • initialScrollIndex is null or ≤ 0 (existing behavior), OR
  • offset > 0 (valid scroll position received)

This prevents the race condition where stale scroll metrics cause incorrect rendering.

Changelog:

[General] [Fixed] - Fix VirtualizedList ignoring initialScrollIndex when scroll event with offset=0 arrives before native scroll completes

Test Plan

  1. Added two new test cases that reproduce the race condition:

    • "does not render items at index 0 when initialScrollIndex is large and scroll event arrives with offset 0" - Tests vertical list
    • "correctly renders at large initialScrollIndex for horizontal list" - Tests horizontal list
  2. Both tests:

    • Create a VirtualizedList with initialScrollIndex=331
    • Simulate layout
    • Simulate a scroll event with offset=0 (reproducing the race condition)
    • Verify items 0-4 are NOT rendered
  3. Before fix: Tests FAIL - items 0-4 render

  4. After fix: Tests PASS - items around 331 remain rendered

  5. All existing VirtualizedList tests continue to pass (76/78, 2 skipped)

Test commands:

# Run new tests
yarn jest packages/virtualized-lists/Lists/__tests__/VirtualizedList-test.js --testNamePattern="does not render items at index 0|correctly renders at large initialScrollIndex"

# Run all VirtualizedList tests  
yarn jest packages/virtualized-lists/Lists/__tests__/VirtualizedList-test.js

…ives with offset=0

When initialScrollIndex > 0, a scroll event with offset=0 could arrive before
the native scroll completes. This would decrement pendingScrollUpdateCount,
allowing _adjustCellsAroundViewport to recalculate the render window using
stale scroll metrics (offset=0), causing items 0-N to render instead of
items around the target initialScrollIndex.

The fix adds a guard to only decrement pendingScrollUpdateCount when:
- initialScrollIndex is null or <= 0 (existing behavior), OR
- offset > 0 (valid scroll position received)

Added two test cases that reproduce the race condition for both vertical
and horizontal lists.
@meta-cla
Copy link

meta-cla bot commented Feb 3, 2026

Hi @ibrahimhajjaj!

Thank you for your pull request and welcome to our community.

Action Required

In order to merge any pull request (code, docs, etc.), we require contributors to sign our Contributor License Agreement, and we don't seem to have one on file for you.

Process

In order for us to review and merge your suggested changes, please sign at https://code.facebook.com/cla. If you are contributing on behalf of someone else (eg your employer), the individual CLA may not be sufficient and your employer may need to sign the corporate CLA.

Once the CLA is signed, our tooling will perform checks and validations. Afterwards, the pull request will be tagged with CLA signed. The tagging process may take up to 1 hour after signing. Please give it that time before contacting us about it.

If you have received this in error or have any questions, please contact us at cla@meta.com. Thanks!

@meta-cla
Copy link

meta-cla bot commented Feb 3, 2026

Thank you for signing our Contributor License Agreement. We can now accept your code for this (and any) Meta Open Source project. Thanks!

@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 Feb 3, 2026
@facebook-github-bot facebook-github-bot added the Shared with Meta Applied via automation to indicate that an Issue or Pull Request has been shared with the team. label Feb 3, 2026
The previous fix only checked offset > 0, which wasn't sufficient for
tiny offsets like 0.008 that arrive before native scroll completes.

Changes:
- Use 10% of expected offset as threshold instead of just > 0
- Add guard in _adjustCellsAroundViewport for direct offset validation
- Add guard in _onScroll for pendingScrollUpdateCount decrement
- Add comprehensive tests simulating Quran app navigation scenario

The dual guards ensure the render window stays correct even when:
1. Scroll events with tiny offsets arrive before native scroll
2. pendingScrollUpdateCount state updates are delayed
@ibrahimhajjaj
Copy link
Author

Updated Fix (Improved)

The fix has been improved based on real-world testing. The changes are:

What Changed

Before: Simple offset > 0 check
After: 10% threshold approach with dual guards

New Implementation

1. _adjustCellsAroundViewport guard (new):
When initialScrollIndex > 0 and getItemLayout is provided, don't adjust the viewport if the scroll offset is less than 10% of expected.

2. _onScroll guard (improved):
Only decrement pendingScrollUpdateCount when offset ≥ 10% of expected offset (instead of just > 0).

Why This Matters

The original offset > 0 check wasn't sufficient - tiny offsets like 0.008 would still pass, causing the render window to jump to index 0.

The 10% threshold:

  • Catches all invalid scroll positions (0, 0.008, 1, etc.)
  • Works correctly for both small and large initialScrollIndex values
  • Minimum threshold of 1 pixel handles edge cases

Test Results

Community verification: This improved fix was tested in a production Quran app:

  • 55/55 successful navigations (100% success rate)
  • Previous success rate: ~50%

New Tests Added

  • "simulates Quran app navigation: maintains correct render window when native scroll is delayed"
  • "scroll events with offset=0 do not prevent scrollToIndex from being called"

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. Shared with Meta Applied via automation to indicate that an Issue or Pull Request has been shared with the team.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants