Skip to content

Commit

Permalink
Fix onEndReached not being called when getItemLayout is present and w…
Browse files Browse the repository at this point in the history
…e scroll past render window (#46736)

Summary:
Pull Request resolved: #46736

Copying the comment in code:

> We only call `onEndReached` after we render the last cell, but when getItemLayout is present, we can scroll past the last rendered cell, and never trigger a new layout or bounds change, so we need to check again after rendering more cells.

Changelog:
[General][Fixed] - Fix onEndReached not being called when getItemLayout is present and we scroll past render window

Reviewed By: yungsters

Differential Revision: D63643856

fbshipit-source-id: 9c53789cb15b225ceac353c37cbb67f7beeaf4fb
  • Loading branch information
NickGerleman authored and facebook-github-bot committed Oct 2, 2024
1 parent b3bc6ea commit 62b7396
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 5 deletions.
18 changes: 18 additions & 0 deletions packages/virtualized-lists/Lists/VirtualizedList.js
Original file line number Diff line number Diff line change
Expand Up @@ -1181,6 +1181,12 @@ class VirtualizedList extends StateSafePureComponent<Props, State> {
if (hiPriInProgress) {
this._hiPriInProgress = false;
}

// We only call `onEndReached` after we render the last cell, but when
// getItemLayout is present, we can scroll past the last rendered cell, and
// never trigger a new layout or bounds change, so we need to check again
// after rendering more cells.
this._maybeCallOnEdgeReached();
}

_cellRefs: {[string]: null | CellRenderer<any>} = {};
Expand Down Expand Up @@ -1491,11 +1497,20 @@ class VirtualizedList extends StateSafePureComponent<Props, State> {
const {
data,
getItemCount,
getItemLayout,
onStartReached,
onStartReachedThreshold,
onEndReached,
onEndReachedThreshold,
} = this.props;
// Wait until we have real metrics
if (
!this._listMetrics.hasContentLength() ||
this._scrollMetrics.visibleLength === 0
) {
return;
}

// If we have any pending scroll updates it means that the scroll metrics
// are out of date and we should not call any of the edge reached callbacks.
if (this.state.pendingScrollUpdateCount > 0) {
Expand Down Expand Up @@ -1538,6 +1553,9 @@ class VirtualizedList extends StateSafePureComponent<Props, State> {
if (
onEndReached &&
this.state.cellsAroundViewport.last === getItemCount(data) - 1 &&
(getItemLayout != null ||
this._listMetrics.getHighestMeasuredCellIndex() ===
getItemCount(data) - 1) &&
isWithinEndThreshold &&
this._listMetrics.getContentLength() !== this._sentEndForContentLength
) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -663,11 +663,6 @@ describe('VirtualizedList', () => {
renderItem: ({item}) => <item value={item.key} />,
getItem: (items, index) => items[index],
getItemCount: items => items.length,
getItemLayout: (items, index) => ({
length: ITEM_HEIGHT,
offset: ITEM_HEIGHT * index,
index,
}),
onEndReached,
};

Expand All @@ -694,6 +689,15 @@ describe('VirtualizedList', () => {
expect(onEndReached).not.toHaveBeenCalled();

await act(() => {
for (let i = 0; i < 20; ++i) {
simulateCellLayout(component, data, i, {
width: 10,
height: ITEM_HEIGHT,
x: 0,
y: i * ITEM_HEIGHT,
});
}

instance._onScroll({
timeStamp: 1000,
nativeEvent: {
Expand Down

0 comments on commit 62b7396

Please sign in to comment.