Summary:
onEndReached can be triggered twice when more items are added to the end of the list. This change makes it so that a second call to onEndReached won't happen until the user scrolls down to the new end of the list.

Changelog:

[General] [Fixed] - Fix double call to onEndReached in VirtualizedList

Reviewed By: sahrens

Differential Revision: D20066740

fbshipit-source-id: 129d7ae6bfd241eeea18fe0bb12b82be67735874
This commit is contained in:
Martin Sherburn 2020-03-27 03:54:58 -07:00 коммит произвёл Facebook GitHub Bot
Родитель d2f314af75
Коммит d3658bc2b6
1 изменённых файлов: 10 добавлений и 11 удалений

Просмотреть файл

@ -1218,8 +1218,6 @@ class VirtualizedList extends React.PureComponent<Props, State> {
componentDidUpdate(prevProps: Props) {
const {data, extraData} = this.props;
if (data !== prevProps.data || extraData !== prevProps.extraData) {
this._hasDataChangedSinceEndReached = true;
// clear the viewableIndices cache to also trigger
// the onViewableItemsChanged callback with the new data
this._viewabilityTuples.forEach(tuple => {
@ -1248,7 +1246,6 @@ class VirtualizedList extends React.PureComponent<Props, State> {
_fillRateHelper: FillRateHelper;
_frames = {};
_footerLength = 0;
_hasDataChangedSinceEndReached = true;
_hasDoneInitialScroll = false;
_hasInteracted = false;
_hasMore = false;
@ -1546,20 +1543,22 @@ class VirtualizedList extends React.PureComponent<Props, State> {
} = this.props;
const {contentLength, visibleLength, offset} = this._scrollMetrics;
const distanceFromEnd = contentLength - visibleLength - offset;
const threshold = onEndReachedThreshold
? onEndReachedThreshold * visibleLength
: 0;
if (
onEndReached &&
this.state.last === getItemCount(data) - 1 &&
/* $FlowFixMe(>=0.63.0 site=react_native_fb) This comment suppresses an
* error found when Flow v0.63 was deployed. To see the error delete this
* comment and run Flow. */
distanceFromEnd < onEndReachedThreshold * visibleLength &&
(this._hasDataChangedSinceEndReached ||
this._scrollMetrics.contentLength !== this._sentEndForContentLength)
distanceFromEnd < threshold &&
this._scrollMetrics.contentLength !== this._sentEndForContentLength
) {
// Only call onEndReached once for a given dataset + content length.
this._hasDataChangedSinceEndReached = false;
// Only call onEndReached once for a given content length
this._sentEndForContentLength = this._scrollMetrics.contentLength;
onEndReached({distanceFromEnd});
} else if (distanceFromEnd > threshold) {
// If the user scrolls away from the end and back again cause
// an onEndReached to be triggered again
this._sentEndForContentLength = 0;
}
}