[FlatList] FlatList unmounts its header component continuously
See original GitHub issueDescription
I have a FlatList with ListHeaderComponent, that is composed with some pickers, when you scroll down or up the header component is being mounted and unmounted continuously, causing the header status to be reset, so pickers will lose their current value.
Reproduction Steps and Sample Code
My implementation:
constructor(props) {
super(props);
this.state = {
refreshing: false,
data: []
};
}
getItemsData(jobList, start, count) {
var data = [];
for (var i = start; i < count + start && i < jobList.length; i++)
{
data.push(jobList[i]);
}
return data;
}
onEndReached() {
this.setState({
data: this.state.data.concat(this.getItemsData(this.props.jobs.jobList, this.state.data.length, 5))
});
}
shouldItemUpdate(props, nextProps) {
if (_.isEqual(props, nextProps))
{
return false;
}
else
{
return true;
}
}
componentWillReceiveProps(nextProps) {
if (nextProps.jobs.jobList.length > 0 && !nextProps.jobs.isFetchingJobList)
{
this.setState({
data: this.getItemsData(nextProps.jobs.jobList, 0, 10)
});
}
}
render() {
return (
<View>
<FlatList
ListHeaderComponent={() => <JobListHeader onApplyFilters={this.onApplyFilters.bind(this)}/> }
data={this.state.data}
renderItem={this.renderItem.bind(this)}
keyExtractor={this.keyExtractor}
numColumns={1}
onEndReached={this.onEndReached.bind(this)}
initialNumToRender={5}
maxToRenderPerBatch={4}
shouldItemUpdate={this.shouldItemUpdate.bind(this)}
onEndReachedThreshold={6}
refreshing={this.state.refreshing}
onRefresh={this.onRefresh.bind(this)}
ref="listRef"
/>
</View>
);
}
JobListHeader render only <View></View>
It seems that onEndReached triggers unmount and mount.
Additional Information
- React Native version: 0.43.2
- Platform: Android
- Development Operating System: Linux
- Dev tools: Android Studio 2.3, Android SDK 23
Issue Analytics
- State:
- Created 6 years ago
- Reactions:7
- Comments:14 (2 by maintainers)
Top Results From Across the Web
How to prevent flatlist header or footer from re-render in ...
This way they will always re-rendering if component will be executed. For performance reasons you better define your function outside and call ...
Read more >Optimizing Flatlist Configuration - React Native
The more complex your components are, the slower they will render. Try to avoid a lot of logic and nesting in your list...
Read more >How to use the FlatList Component — React Native Basics
What is the FlatList component? It's an easy way to make an efficient scrolling list of data. Not only is it efficient but...
Read more >Optimizing React performance by preventing unnecessary re ...
Re-rendering React components unnecessarily can slow down your app and make the UI feel unresponsive. This article explains how to update ...
Read more >How To Prevent A Header Of Flatlist From Going Down When ...
. that I replace the pager buttons with a continuously refreshing or infinite scrolling list. I assigned it a header component that renders...
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
This is a little nuanced…
tl;dr: always pre-bind functions you pass as props so you don’t re-create the function on every render.
So
ListHeaderComponent
is of typeReactClass
, which means that when you pass in a function like you’re doing, it’s not just called as a plain function (likerenderItem
), but as a stateless, functional react component (hence the name…*Component
). This means that if you re-create and re-bind the function inrender
like you are doing (e.g. any time you callsetState
inonEndReached
), React will treat it as a new react component class and will destroy and recreate the instance every time, just as if you were switching back and forth between<Text>
and<View>
.I would recommend turning that function into an autobound method like so:
then when you set the prop, it will always be the same thing and react will update the instance rather than re-creating from scratch:
If the auto-binding initializer syntax doesn’t work for you for some reason, you can bind it in the constructor instead.
I also recommend auto-binding for all your other props as well, like
renderItem
, because it will skip unnecessary work and wasted memory with constantly re-binding the same functions, and will skip unncessary re-renders when doing thePureComponent
shallow equality checks.Couple other notes:
shouldItemUpdate
was deprecated so it no longer does anything.