I am facing some trouble using the List View onEndReached component in react native.
Render code:
@autobind
_fetchMoreHistory(){
console.log("Fetch more history called");
}
<View style={[styles.Ctr]}>
<ListView dataSource={this.state.txHistorySource}
renderRow={ this._renderRow }
onEndReached ={ this._fetchMoreHistory }
onEndReachedThreshold = {10}/>
</View>
The moment I open the screen _fetchMoreHistory
is called twice and works normally after that onEndReached
reached. Can someone help debug this ?
I am facing some trouble using the List View onEndReached component in react native.
Render code:
@autobind
_fetchMoreHistory(){
console.log("Fetch more history called");
}
<View style={[styles.Ctr]}>
<ListView dataSource={this.state.txHistorySource}
renderRow={ this._renderRow }
onEndReached ={ this._fetchMoreHistory }
onEndReachedThreshold = {10}/>
</View>
The moment I open the screen _fetchMoreHistory
is called twice and works normally after that onEndReached
reached. Can someone help debug this ?
- How many rows are you fetching? onEndReached is executed at the end of the rendering of the rows, so you set the limit to 10, I think you have just more thant 10 rows. It's possible? – Mario Santini Commented Dec 23, 2016 at 7:36
- Does this answer your question? FlatList calls `onEndReached` when it's rendered – luke77 Commented Oct 30, 2020 at 12:12
6 Answers
Reset to default 6I had the same issue. But I figured out that I had the ScrollView
that wraps my FlatList
.
When I removed it all started working properly.
It's a pity that NOTHING WAS SAID ABOUT THAT IN THE OFFICIAL DOCS
I faced the same issue and searched a lot but didn't find any answers, so I used a condition to check if the first request got the data I fire onendreashed again else I don't
Example // onEndReached If(condition) { Make the call }
So my solution is simple. Don't use onEndReached
at all. Use onScroll
and detect the end of the scroll.
isCloseToBottom = ({ layoutMeasurement, contentOffset, contentSize }) => {
const paddingToBottom = 20; // how far from the bottom
return layoutMeasurement.height + contentOffset.y >=
contentSize.height - paddingToBottom;
};
and the FlatList
component
<FlatList
data={data}
onScroll={({ nativeEvent }) => {
if (this.isCloseToBottom(nativeEvent)) {
// Dont forget to debounce or throttle this function.
this.handleOnEndReached();
}
}}
/>
You can try my solution
- You should configure limit > 10. Example limit = 15
Add onMomentumScrollBegin prop to your ListView declaration.
<ListView data={this.props.data} onEndReached={...} onEndReachedThreshold={0.5} ... onMomentumScrollBegin={() => { this.onEndReachedCalledDuringMomentum = false; }} />
Modify your onEndReached callback to trigger data fetching only once per momentum.
onEndReached =()=> { if(!this.onEndReachedCalledDuringMomentum) { this.props.fetchData(); this.onEndReachedCalledDuringMomentum = true; } };
I've solved this problem by creating a state variable that tells me is the service is loading or not.
class Component1 extends Component {
public constructor(props) {
super(props);
this.state = {
isLoading: false,
listOfItems: []
};
}
public componentDidMount() {
this.loadData();
}
public render(){
return (
<FlatList
data={this.state.listOfItems}
renderItem={this.renderItem}
onEndReachedThreshold={0.1}
onEndReached={this.loadData}
/>
);
}
private loadData = () => {
if (this.state.isLoading === true) {
/// Avoid make another request is there's happening a request right now
return;
}
this.setState({isLoading: true});
this.fetchData()
.then(() => {
/// Handle success response
this.setState({isLoading: false});
})
.catch(() => {
this.setState({isLoading: false});
});
}
}
You can write the code for fetching data in onMomentumScrollEnd
rather than onEndReached
, like this:
onMomentumScrollEnd={() => this.props.onEndReached()}
It might not be written as the available prop in the react native documentation, but if you will see the source code for FlatList
, it uses Virtualized List
which in return has the mentioned prop available.