fix: reset pendingStartReached when data changes - #2429
Open
sergeymild wants to merge 1 commit into
Open
Conversation
pendingEndReached is reset on every data change, but pendingStartReached is not. onStartReached is edge-triggered off pendingStartReached, so once it latches true it only re-arms when isNearStart briefly reads false — which the maintainVisibleContentPosition offset adjustment after a backward prepend doesn't reliably guarantee before the next bounds check. Observed in an inverted list with maintainVisibleContentPosition + onStartReached prepending pages of older items: after a handful of successful backward loads, onStartReached stopped firing entirely, with no error and no further callback invocations, until the list was scrolled away from the start and back. Resetting pendingStartReached alongside pendingEndReached on data change closes that race.
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
pendingEndReachedis reset tofalseon everydatachange, butpendingStartReachedis not:onStartReached/onEndReachedare edge-triggered off these refs:In a normal "load older items on scroll to top" pagination flow (inverted list,
maintainVisibleContentPosition,onStartReachedprepending a page of older items todata), we sawonStartReachedstop firing entirely after a handful of successful backward loads — no further call, no error, nothing — until the list was scrolled away from the start past the threshold and back.Suspected mechanism
After
onStartReachedfires and the app prepends older items,maintainVisibleContentPositionadjusts the scroll offset to keep the visible content stable. Depending on timing, thecheckBoundspass right after that adjustment can still readlastScrollOffsetas withinstartThresholdDistance(especially with a multi-viewportonStartReachedThreshold), soisNearStartnever dips tofalsebetween oneonStartReachedcall and the nextdataupdate. SincependingStartReachedisn't part of the[data]reset (unlikependingEndReached), the latch then staystrueand blocks every subsequent call.This is timing/threshold-dependent, so it doesn't reproduce on every load — in our repro it took ~8 successful backward loads before it latched.
Fix
Reset
pendingStartReachedin the same placependingEndReachedis reset, mirroring the existing behavior for the end-of-list case.Testing
Verified manually against a production chat screen with 1000+ items: before this change, repeated scroll-to-top pagination reliably stopped firing
onStartReachedafter ~8 consecutive backward loads. With the fix, 25+ consecutive backward loads succeeded with no stall.I don't have a minimal standalone repro repo, but can put one together if that's useful for review.
@shopify/flash-list: 2.3.2react-native: 0.84.1