React-Native FlatList ListHeaderComponent ignores shouldComponentUpdate - react-native

In React-Native, using a FlatList with a ListHeaderComponent lets me to believe that the shouldComponenupdate function in the ListHeaderComponent (though executed) is ignored. My component always rerenders even though I return false in shouldComponentUpdate. How would I stop the ListHeaderComponent from rerendering?
<Card>
<FlatList data={comments}
ListHeaderComponent={() => <PostHeader navigation={this.props.navigation} post={this.props.post} />}
style={{flex:1}}
onRefresh={() => this.props.getPost(mediaId, 'newsfeed', true)}
refreshing={isRefreshing}
keyExtractor={(comment) => comment.id}
removeClippedSubviews={false}
renderItem={(comment) => <Comment comment={comment.item} /> } />
<PostComment newComment={newComment}
postComment={() => this.props.postComment(newComment.content, mediaId, profile.id)}
reset={()=> this.props.resetNewComment}
onTextChange={this.props.newCommentTextChanged} />
{Platform.OS.toLocaleLowerCase() === 'ios' &&
<KeyboardSpacer />
}
</Card>
Placing the before the FlatList stops the undesired behavior, but this would require wrapping the lot in a ScrollView which I rather avoid when using a FlatList.

Turns out, it wasn't rerendering, it was unmounting en mounting my component due to this:
https://github.com/facebook/react-native/issues/13602#issuecomment-300608431

Related

VirtualizedLists should never be nested error

I'm building a mobile application with React Native, and I have a ScrollView inside one of the pages.
The problem is that I have in this page a FlatList so when I go to that page, I get this error:
VirtualizedLists should never be nested inside plain ScroolViews with the same orientation... The thing is, I set the ScrollView nestedScrollEnabled to true and I also set the FlatList's scrollEnabled to false because I don't really need the scroll there (I'm using it to render items from an enum) so I thought that should fix the error, but the error still persist.
It looks like this:
<ScrollView showsVerticalScrollIndicator={false} nestedScrollEnabled={true}>
<MyComponent />
</ScrollView>
And MyComponent has this FlatList:
<FlatList
scrollEnabled={false}
style={{padding: 8,marginBottom: 8,}}
data={categories}
numColumns={numOfColumns}
keyExtractor={category => category}
renderItem={item => renderItem(item.item)}
/>
Can you try to add the property nestedScrollEnabled={true} to both the parents and the children:
<ScrollView showsVerticalScrollIndicator={false} nestedScrollEnabled={true}>
<MyComponent />
</ScrollView>
<FlatList
nestedScrollEnabled={true}
scrollEnabled={false}
style={{padding: 8,marginBottom: 8,}}
data={categories}
numColumns={numOfColumns}
keyExtractor={category => category}
renderItem={item => renderItem(item.item)}
/>
You can use the ListHeaderComponent and ListFooterComponent of the FlatList to render the other parts inside the scrollView. Using a FlatList inside a scrollview limits the performance of the FlatList.
<FlatList
ListHeaderComponent={
<>
<AboveFlatList />
</>
}
data={yourData}
renderItem={this.renderComponents}
...
...
ListFooterComponent={
<>
<BelowFlatList />
</>
}
/>

React native Flatlist TouchableOpacity OnPress Not Working On Android

Can some help me with this issue. On press not working in Flatlist render function. here my code. i checked other screens touch case working fine but when i try it in Flatlist it's not working
render(){
return (
<View style={styles.container} >
<FlatList
data={this.state.categories}
numColumns={2}
keyExtractor={item => item.id}
renderItem={item => this.renderItem(item)}
/>
</View>
);
}
renderItem = ({item,index}) => {
return (
<TouchableOpacity onPress={() => this.moveToLocation(item.id)} style={styles.items}>
<Image source={{uri:item.img}}
resizeMode="center"
style={styles.itemsimg} />
<Text style={{textAlign:'center',fontSize:20, }} onPress={() => this.moveToLocation(item.id)}>{item.name}</Text>
</TouchableOpacity>
);
}
You need to wrap your row element (inside your renderItem method) inside tag. TouchableWithoutFeedback takes onPress as it's prop where you can provide onPress event.
For TouchableWithoutFeedback refer
https://facebook.github.io/react-native/docs/touchablewithoutfeedback.html
if onPress is not workingin the flatlist's render method try using onTouchStart method of the components if they have in the flatList's render method.

How do I render different data types from a fetched json?

I was using...
<FlatList
data={this.state.dataSource}
renderItem={({item}) => <Text>{item.username} {item.name}</Text>}
keyExtractor={({id}, index) => id}
/>
...to render two texts in React Native but now I've got an uri in my json...
How do I render the image in an IM style (thumbnail, username and name)?
Add a renderItem method and then put everything you need in there. Once you make the renderItem method you can throw it into your FlatList.
renderItem({ item }) {
return (
<View>
<Image
source={{uri: item.uri}}
/>
<Text>
{item.username}
</Text>
<Text>
{item.name}
</Text>
</View>
);
}
Then use the method inside the FlatList (the .bind makes sure it stays in the right context)
<FlatList
data={this.state.dataSource}
renderItem={this.renderItem.bind(this)}
keyExtractor={({id}, index) => id}
/>
You can build a component that takes your fields as its props, containing multiple Texts and an Image using your uri as the source. Style this like you would any other component, and then pass that component into renderItem.
You can embed the component immediately to the renderItem like this if the flatlist item is not complicated ( has a lot of component )
<FlatList
data={this.state.dataSource}
renderItem={({item}) => {
<View>
<Image source={{uri: item.uri.image}}/>
<Text>{item.userName}</Text>
<Text>{item.name}</Text>
</View>
}}
keyExtractor={(i) => i.toString()}
/>

React Native FlatList inside ScrollView onEndReached never called

My container is a scrollview and inside it is a flatlist, which load data from server.
The flatlist:
<VirtualizedList
ListEmptyComponent={<NoData />}
data={data}
getItem={(items, index) => items.get(index)}
getItemCount={(items) => items.size}
keyExtractor={(item, index) => String(index)}
renderItem={this._renderItem}
refreshControl={
<RefreshControl
refreshing={loading}
onRefresh={this._onRefresh.bind(this)}
/>
}
onEndReached={this.handleLoadMore}
onEndReachedThreshold={0.1}
onMomentumScrollBegin={() => {
Log('onMomentumScrollBegin fired!')
this.onEndReachedCalledDuringMomentum = false;
}}
/>
which handleLoadMore is:
handleLoadMore = () => {
Log('handleLoadMore fired!');
if (!this.onEndReachedCalledDuringMomentum) {
// fetch data..
this.onEndReachedCalledDuringMomentum = true;
}
}
The problem is the handleLoadMore never called and the onMomentumScrollBegin also never called.
How to solve this?
Actually you don't need to use Content or ScrollView as FlatList has both ListFooterComponent and ListHeaderComponent
In case you really need to use FlatList inside ScrollView, then add style and content contentContainerStyle to your ScrollView or if you use native-base, inside the Content
<ScrollView
...
style={{flex: 1}}
contentContainerStyle={{flex: 1}}
...
/>
Then if you want to use header component out of FlatList loop. Then use ListHeaderComponent={() => <SomeHeader /> inside Flatlist.

onEndReached in Flatlist issue

If I enclose the flatlist in a View then my onEndReached triggers infinitely if I remove the enclosing View onEndReached is not triggered at all.
render() {
return (
<Root>
<Container>
<Content>
<View>
{this.state.listView && (
<FlatList
data={this.state.variants}
keyExtractor={this._keyExtractor}
onEndReachedThreshold={0.5}
onEndReached={({ distanceFromEnd }) => {
console.log(
"on end reached ",
distanceFromEnd
);
this.loadMore();
}}
numColumns={1}
renderItem={({ item, index }) => (
<CatalogRow
item={item}
in_wishlist={this.state.in_wishlist}
toggleWishlist={() =>
this.toggleWishlist(item.title)
}
listView={this.state.listView}
/>
)}
/>
)}
</View>
</Content>
</Container>
</Root>
);
}
And my distanceFromEnd takes values like 0 , 960,1200 when it is trigerred. What does it indicate?
I'm using react-native 0.47.2
I have same problem with react-native 0.50.3
<Flatlist> must not be used in a <ScrollView> if you want to use onEndReached because Flatlist can not found the height.
Use a <View> instead
It was because of the enclosing <Content> tag. Sometimes embedding react-native tags with native-base tags causes such issues. I replaced the content and container tag with View tags and now it works fine.
I have same problem with RN 0.52
That look like because Flatlist can not found the heigh. So he can not find the end of list.
Fix by wrap your flatlist by a View with flex=1
<View style={{flex: 1}} > <Flatlist /> <View>
I would use it like this:
handleMore = () => {
// fetch more here
};
<FlatList
onEndReached={this.handleMore}
/>