react-native: FlatList onEndReached triggered before reach onEndReachedThreshold

Description

FlatList onEndReached triggered before reach end of list. If legacyImplementation is set to true or render with ListView, onEndReached will trigger correctly when it reached end of list

Reproduction

Based from FlatListExample on UIExplorer in React Native v0.43.0-rc.1, add onEndReached to FlatList

state = {
  data: genItemData(30),
  debug: false,
  horizontal: false,
  filterText: '',
  fixedHeight: true,
  logViewable: false,
  virtualized: true,
};

<FlatList
  HeaderComponent={HeaderComponent}
  FooterComponent={FooterComponent}
  SeparatorComponent={SeparatorComponent}
  data={filteredData}
  debug={this.state.debug}
  disableVirtualization={!this.state.virtualized}
  getItemLayout={this.state.fixedHeight ?
    this._getItemLayout :
    undefined
  }
  horizontal={this.state.horizontal}
  key={(this.state.horizontal ? 'h' : 'v') +
    (this.state.fixedHeight ? 'f' : 'd')
  }
  legacyImplementation={false}
  numColumns={1}
  onRefresh={this._onRefresh}
  onViewableItemsChanged={this._onViewableItemsChanged}
  ref={this._captureRef}
  refreshing={false}
  renderItem={this._renderItemComponent}
  shouldItemUpdate={this._shouldItemUpdate}
  viewabilityConfig={VIEWABILITY_CONFIG}
  onEndReachedThreshold={1}
  onEndReached={({ distanceFromEnd }) => {
    console.log('on end reached ', distanceFromEnd)
  }}
/>  

Additional Information

  • React Native version: v0.43.0-rc.1
  • Platform: Both
  • Operating System: MacOS

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Reactions: 16
  • Comments: 40 (5 by maintainers)

Commits related to this issue

Most upvoted comments

I believe Content is from NativeBase and I believe that implements a ScrollView. FlatList cannot work right inside a ScrollView.

I know how to solve this, you just need to set onEndReachedThreshold as a rate of visibleLength. So you just need to set it as a number smaller than 1, then it worked!!!

Try this onEndReachedThreshold={0.01}

If onEndReachedThreshold > 0 then it is triggered 2 times…

Ok so in my case issue was because I was using Listview inside Content from NativeBase using it inside Container fixed the issue

onEndReachedThreshold?: ?number

How far from the end (in units of visible length of the list) the bottom edge of the list must be from the end of the content to trigger the onEndReached callback. Thus a value of 0.5 will trigger onEndReached when the end of the content is within half the visible length of the list.

As quoted in updated doc regarding onEndReachedThreshold on http://facebook.github.io/react-native/releases/0.44/docs/flatlist.html#onendreachedthreshold We will need to set value range from 0 to 1 where value of 0.5 will mean half the visible length of the list

The denouncing is based on state changes, so if you rerender anything or update the data in response to the callback or after it’s called the first time, it might get called again.

I have this problem too it really needs to be fixed , it really drive me crazy ! (and yes i used it inside the Container component from NativeBase )

Is there any function called when scroll reached start. Something like onStartReached() ???

also encountering this problem

I understand @sahrens 's comment “The denouncing is based on state changes, so if you rerender anything or update the data in response to the callback or after it’s called the first time, it might get called again.”

But how can we prevent it from calling onEndReached when it’s re-rendered???

return (
  <View style={{ flex:1 }}>
    <FlatList
      data={this.props.categories}
      renderItem={this._renderItem}
      keyExtractor={this._keyExtractor}
      numColumns={2}
      style={{flex: 1, flexDirection: 'row'}}
      contentContainerStyle={{justifyContent: 'center'}}
      refreshControl={
        <RefreshControl
          refreshing = {this.state.refreshing}
          onRefresh = {()=>this._onRefresh()}
        />
      }
      // curent value for debug is 0.5
      onEndReachedThreshold={0.5} // Tried 0, 0.01, 0.1, 0.7, 50, 100, 700

      onEndReached = {({distanceFromEnd})=>{ // problem
        console.log(distanceFromEnd) // 607, 878 
        console.log('reached'); // once, and if I scroll about 14% of the screen, 
                             //it prints reached AGAIN. 
        this._onEndReachedThreshold()
      }}
    />
  </View>
)

More: https://stackoverflow.com/questions/47910127/flatlist-calls-enendreached-when-its-rendered

i tried setting onEndReachedThreshold to 0.5, now I’m halfway of my flat list, and onEndReached() is not triggered, i tried scrolling past it, reaching the very end of the list, still the onEndReached() is not triggered.

Why is it not working on android?

<Content>
                       <FlatList
                           data={this.props.destination_place_list}
                           renderItem={this.renderItem}
                           keyExtractor={item => item.id}
                           onEndReached={(xxx) => {
                                   console.log(xxx);
                                   this.handleLoadMore.bind(this);
                               }
                           }
                           onEndReachedThreshold={0.5}
                       />
</Content>

I’m using android and react-native 0.45. Have you guys fixed the issue?

@alphasp I have not yet played around with FlatList, but is there any chance that the onEndReachedThreshold has some default non-zero value you are unaware of?

`constructor(props){ super(props); this.state = { flatListReady:false } }

_scrolled(){ this.setState({flatListReady:true}) }

loadMore = () => { if(!this.state.flatListReady){ return null}

//you can now load more data here from your backend

} <FlatList onScroll={this._scrolled.bind(this)} style={{width:‘100%’,flexGrow:1}} ListHeaderComponent={this.headerComponent} data={this.props.data} renderItem={this.renderItem} keyExtractor={(item,index) => index } onEndReached={(x) => {this.loadMore()}} onEndReachedThreshold={0.5}

       />

`

@sahrens My Flatlist like this:

 var flatList = <FlatList
                style={styles.lStyle }
                data={this.state.dataSource2}
                renderItem={ItemRowYesterdaySignal.bind(this)}
                onEndReachedThreshold={10}
                onEndReached={({ distanceFromEnd }) => {
                   this._ItemLoadMore();
                }}
                ref='_flatList'
            />;
_ItemLoadMore(){
        if (this.state.current_page +1 <= this.state.total_pages)
        {
            if (this.keyword  && this.keyword !='')
            {
                var page = this.state.current_page+1;
                this.search(this.keyword, page)
            }
            else
            {
                this.loadMore(this.state.current_page+1)
            }
        }
    }

Thanks for your comment.

@ramilushev Yes, just checked the code, created a PR to make it behave like ListView implementation