I am new in react native and developing a mobile application in React-Native.
At one screen I have used Flatlist to show number of video items, and there is one header and footer also required in that particular scree. The thing is working well but when I put console in header and footer component then I got to know that these component are re-rendring number of time. So ho can I restrict them to re-render. I have used various way to handle but nothing get help me.
Here is the code of my screen where I am using this thing.
return (
<>
<View style={styles.videosView}>
<FlatList
windowSize={6}
initialNumToRender={10}
showsHorizontalScrollIndicator={false}
showsVerticalScrollIndicator={false}
numColumns={2}
data={pozzles?.length % 2 === 0 ? pozzles : [...pozzles, {}]}
ListHeaderComponent={userInfoHeader}
renderItem={renderItem}
ListFooterComponent={videoListFooter}
columnWrapperStyle={styles.coloumContainer}
style={styles.videoListStyle}
contentContainerStyle={styles.videoListContentStyle}
ListFooterComponentStyle={{ backgroundColor: Colors.GRAYOFF }}
keyExtractor={item => item._id}
onEndReached={onEndReachCall}
onEndReachedThreshold={0.01}
/>
</View>
</>
);
And here is the header and footer component :-
function userInfoHeader() {
console.log('Header rendring.....');
return (
<VStack justify="space-evenly" style={styles.editView}>
<HStack style={styles.userSummary}>
<Image
style={styles.userImage}
source={{
uri:
user?.user?.profilePhoto !== ''
? user?.user?.profilePhoto
: pozzlePilot,
}}
height={112}
width={112}
/>
............
</HStack>
</VStack>
}
)
Footer :-
function videoListFooter() {
console.log('Footer rendring.....');
return (
<View style={styles.footerStyle}>
{user?.user?.pozzleVideos === 0 ? (
<>{noVideoYetLabel()}</>
............
</View >
}
)
Can someone please help me to restrict that re-rendring....
Related
I am looking at React Native Sticky Parallax Header library ( https://netguru.github.io/sticky-parallax-header/docs/headers/tabbed-header-pager ) and I'm a bit confused about it.
I want to have a 'Tabbed Header Pager', but with a custom Header, which seems to be not possible through inbuilt options. I tried creating a view on top of the tabs and animating it myself, but still the 4 tabs ( each containing flatlist) are not performant.
Custom Sticky Header StickyHeaderScrollView looks good to my requirements, But I am not sure how to get the tabs working on it. I see renderTabs method , but the tabs aren't visible. No props for supplying the tabs[]
How to achieve the 'Tabbed Header Pager' with a custom header?
<View style={{flex: 1}}>
<StickyHeaderScrollView
ref={scrollViewRef}
onScroll={onScroll}
renderTabs={() => renderTabs(1)}
stickyTabs
onMomentumScrollEnd={onMomentumScrollEnd}
onScrollEndDrag={onScrollEndDrag}
showsVerticalScrollIndicator={false}
renderHeader={() => (
<View style={{}}>
<UserProfileHeaderComponent {...profileData} />
</View>
)}
style={{flex: 1, borderWidth: 0}}
/>
</View>
and below my renderTab component
const renderTabs = (tabIndex: number) => {
switch (tabIndex) {
case 1:
return (
<TabOneComponent
username={username}
refreshingTabs={refreshingTabs}
setRefreshingTabs={setRefreshingTabs}
onLikeItem={onLikeItem}
currentTabIndex={currentTabIndex}
loadMoreHeight={loadMoreHeight < 1000 ? loadMoreHeight : 1000}
onBottomSheetItemClick={onBottomSheetItemClick}
/>
);
case 2:
return (
<TabTwoComponent
username={username}
onLikeItem={onLikeItem}
refreshingTabs={refreshingTabs}
setRefreshingTabs={setRefreshingTabs}
currentTabIndex={currentTabIndex}
loadMoreHeight={loadMoreHeight < 1000 ? loadMoreHeight : 1000}
onBottomSheetItemClick={onBottomSheetItemClick}
/>
);
case 3:
return (
<MediaTabComponent
username={username}
onLikeItem={onLikeItem}
refreshingTabs={refreshingTabs}
setRefreshingTabs={setRefreshingTabs}
currentTabIndex={currentTabIndex}
loadMoreHeight={loadMoreHeight < 1000 ? loadMoreHeight : 1000}
onBottomSheetItemClick={onBottomSheetItemClick}
/>
);
case 4:
return (
<LikedTabComponent
username={username}
onLikeItem={onLikeItem}
refreshingTabs={refreshingTabs}
setRefreshingTabs={setRefreshingTabs}
currentTabIndex={currentTabIndex}
loadMoreHeight={loadMoreHeight < 1000 ? loadMoreHeight : 1000}
onBottomSheetItemClick={onBottomSheetItemClick}
/>
);
default:
return <></>;
}
};
I am trying to achieve pagination for infinite scrolling in react native. When loading, I want to render the loading spinner at the bottom of the Flat list component. (Note: I'm using Expo for this app)
const renderFooter = () => {
if (!category.loading) return null;
return (
<View style={spinnerStyles.container}>
<ActivityIndicator animating size="large" color="#0000ff" />
</View>
);
};
return (
<View style={styles.container}>
<FlatList
columnWrapperStyle={{ justifyContent: "space-between" }}
numColumns={2}
data={category.data}
renderItem={categoryItem}
keyExtractor={(item) => item._id + item.sub_category}
onEndReachedThreshold={0}
listFooterComponent={renderFooter}
onEndReached={() => loadMore()}
/>
</View>
);
The loading spinner not correctly working with the flat list footer.
Has anyone run into this issue before, or does anyone have a solution?
Sorry, it's my simple syntax error. It's actually ListFooterComponent not listFooterComponent. Now it's working fine, Thank you.
Instead of calling the refrence, call the function. It should look something like this.
ListFooterComponent={renderFooter()}
I have flat list that is returning a JSON feed with nested objects / arrays. All is working except horizontal listing, it still lists each item vertically. Does anyone know how I can list the returned images horizontally instead of vertically?
{isLoading ? <ActivityIndicator/> : (
<FlatList
data={[data]}
horizontal={true}
keyExtractor={({ id }, index) => id}
renderItem= {({ item, index }) => (
<View>
{item.items.map((v, i) => (
<TouchableOpacity onPress={() => props.navigation.navigate('Pdp', {articleid: item.id})}>
<View style={styles.container}>
<Image style={styles.imgyoutubeprev} source={{ uri: chkValue(v.snippet.thumbnails.high.url) }} />
<Image style={styles.imgyoutubebtnoverlay} source={require('../assets/youtubebtn.png')} />
</View>
</TouchableOpacity>
))}
</View>
)}
/>
)}
We would need to have a bit more information about the styles that you are using. If the items are rendered vertically instead of horizontal then this is likely caused by the element that surrounds the FlatList.
Make sure that the View or other component that contains the FlatList has the flex: 1 style or at least takes up the full width. Otherwise the horizontal elements would still wrap and be rendered vertically.
Bonus tip: You might be able to remove the View child from the TouchableOpacity by moving the styles.container to the TouchableOpacity and then replacing the inner View with a Fragment.
Thanks all. The big difference was removing the view surrounding the item.items.map. I haven't had to force flex: 1 against the view, though I have forced flex 1 across the whole screen, so possibly thats helped as well. Thanks again all.
The code I used (taking on your code reduction, and is working as expected is;
return (
<View>
{isLoading ? <ActivityIndicator/> : (
<FlatList
data={[data]}
horizontal={true}
horizontal
keyExtractor={({ id }, index) => id}
renderItem= {({ item, index }) => (
item.items.map((v, i) => (
<TouchableOpacity onPress={() => props.navigation.navigate('Pdp', {articleid: item.id})}>
<Image style={styles.imgyoutubeprev} source={{ uri: chkValue(v.snippet.thumbnails.high.url) }} />
<Image style={styles.imgyoutubebtnoverlay} source={require('../assets/youtubebtn.png')} />
</TouchableOpacity>
))
)}
/>
)}
</View>
);
};
I you put an Algolia connected component in a header of a FlatList it's as if it enters an infinite loop of queries. The connectInfiniteHits runs constantly.
This is really annoying if you like to put some simple filters in the headers of a list of hits.
My setup is like this:
I have a FlatList that is wrapped by the connectInfiniteHits HOC.
The ListHeaderComponent contains a component this is wrapped by the connectRefinementList HOC. The same problem occurs with a connectSearchBox HOC.
Has anyone seen this and found a solution?
I manage to make it work with those lines:
const RefinementList = connectRefinementList(({ items, refine }) => (
<View>
{items.map(item => (
<TouchableOpacity key={item.label} onPress={() => refine(item.value)}>
<Text style={{ fontWeight: item.isRefined ? '600' : 'normal' }}>
{item.label}
</Text>
</TouchableOpacity>
))}
</View>
));
const InfiniteHits = connectInfiniteHits(({ hits, hasMore, refine }) => (
<FlatList
data={hits}
keyExtractor={item => item.objectID}
onEndReached={() => hasMore && refine()}
ListHeaderComponent={<RefinementList attribute="brand" />}
renderItem={({ item }) => (
<View>
<Text>{JSON.stringify(item).slice(0, 100)}</Text>
</View>
)}
/>
));
Note that I'm not using the function version which indeed breaks.
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}
/>