'Using react memo to avoid re render each item on flatlist isnt working
im using react memo to avoid the re render of each item of the flatlist when scrolling, if that item is already render why it should runs the useEffect again? i need to do that because my app needs it, here is the structure for now:
flatlist:
<FlatList
style = {{
width: Dimensions.get("window").width
}}
bounces={false}
ref={FlatListRef}
data = {[]}
onScroll={({nativeEvent}) => {
const scrolling = nativeEvent.contentOffset.y;
if (scrolling > 200) {
if(scrollOver==false) {
Animated.timing(logoTranslationX, {
toValue: -15,
duration: 400,
useNativeDriver: true,
easing: Easing.out(Easing.quad),
}).start();
Animated.timing(logoScale, {
toValue: 0.8,
duration: 400,
useNativeDriver: true,
easing: Easing.out(Easing.quad),
}).start();
Animated.timing(logoAOpactiy, {
toValue: 0,
duration: 400,
useNativeDriver: true,
easing: Easing.out(Easing.quad),
}).start();
Animated.timing(logoBOpactiy, {
toValue: 1,
duration: 400,
useNativeDriver: true,
easing: Easing.out(Easing.quad),
}).start();
scrollOver=true
parent_flatlist_scroll.current = true;
}
} else {
if(scrollOver==true) {
Animated.timing(logoTranslationX, {
toValue: 0,
duration: 400,
useNativeDriver: true,
easing: Easing.in(Easing.quad),
}).start();
Animated.timing(logoScale, {
toValue: 1,
duration: 400,
useNativeDriver: true,
easing: Easing.in(Easing.quad),
}).start();
Animated.timing(logoAOpactiy, {
toValue: 1,
duration: 400,
useNativeDriver: true,
easing: Easing.in(Easing.quad),
}).start();
Animated.timing(logoBOpactiy, {
toValue: 0,
duration: 400,
useNativeDriver: true,
easing: Easing.in(Easing.quad),
}).start();
scrollOver=false
}
}
}}
showsVerticalScrollIndicator = {false}
data={dataSource}
// decelerationRate={0.995}
windowSize={6}
initialListSize={10}
initialNumToRender={15}
maxToRenderPerBatch={30}
keyExtractor={(item) => item.uuid}
showsVerticalScrollIndicator={false}
showsHorizontalScrollIndicator={false}
scrollEventThrottle={500}
renderItem = {({item, index}) => {
return (
<PublicationsMemo
data = {item}
index = {index}
top = {dataSourceTop}
>
</PublicationsMemo>
)
}}
onEndReachedThreshold = {0.3}
onEndReached = {loadMore}
ListFooterComponent={<CustomLoader/>}
ListHeaderComponent = {renderHeader()}
>
</FlatList>
publications memo component:
const Publications = (props) => {
const [uuid, setUuid] = useState(props.data.uuid);
const [item, setItem] = useState(props.data);
const [index, setIndex] = useState(props.index);
const [top, setTop] = useState(props.top);
useEffect(() => {
console.log("re render", index, item.title);
}, []);
return (
<>
{
(index % 5 === 0) ?
<>
<View style={{flex:1, overflow: "hidden", marginBottom: 10, alignItems: "center"}} key = {uuid}>
<View style={[{height:ITEM_HEIGHT, flexDirection: "row"}]}>
<TouchableOpacity activeOpacity={0.8}>
<SharedElement id={`item.${item.uuid}.photo`}>
<ExpoFastImage
style={{
width: ITEM_WIDTH,
height: 'auto',
aspectRatio: 16 / item.poster_align, //minimun 10, using aspect ratio because they want to choose which section of the image will be the preview
}}
uri={item.thumbnail}
cacheKey={item.uuid + 'thumbnail'}
resizeMode = "cover"
/>
</SharedElement>
</TouchableOpacity>
<View style={{flex:1,padding:15,paddingTop:0,height:ITEM_HEIGHT}}>
{item.category && <Text style={[styles.subtitle,{marginTop:0}]}>{item.category.name}</Text>}
<TouchableOpacity activeOpacity={0.8}>
<Text numberOfLines={2} style={styles.title}>{item.title}</Text>
</TouchableOpacity>
<DateTimeBlock item={item} />
<Voting
item={item} style={{position:'absolute',bottom:0,left:15,opacity:0.8}}
title={34}
index = {index}
// fetch_data = {fetchData}
/>
</View>
</View>
</View>
<Drop data = {top}></Drop>
</>
:
<View style={{flex:1, overflow: "hidden", marginBottom: 10, alignItems: "center"}} >
<View style={[{height:ITEM_HEIGHT, flexDirection: "row"}]}>
<TouchableOpacity activeOpacity={0.8}>
<SharedElement id={`item.${item.uuid}.photo`}>
<ExpoFastImage
style={{
width: ITEM_WIDTH,
height: 'auto',
aspectRatio: 16 / item.poster_align, //minimun 10, using aspect ratio because they want to choose which section of the image will be the preview
}}
uri={item.thumbnail}
cacheKey={item.uuid + 'thumbnail'}
resizeMode = "cover"
/>
</SharedElement>
</TouchableOpacity>
<View style={{flex:1,padding:15,paddingTop:0,height:ITEM_HEIGHT}}>
{item.category && <Text style={[styles.subtitle,{marginTop:0}]}>{item.category.name}</Text>}
<TouchableOpacity activeOpacity={0.8}>
<Text numberOfLines={2} style={styles.title}>{item.title}</Text>
</TouchableOpacity>
<DateTimeBlock item={item} />
<Voting
item={item} style={{position:'absolute',bottom:0,left:15,opacity:0.8}}
title={34}
index = {index}
// fetch_data = {fetchData}
/>
</View>
</View>
</View>
}
</>
)
}
const equal = (prev, next) => {
if(prev.index === next.index) {
return false;
}else {
return true;
}
}
export const PublicationsMemo = React.memo(Publications, equal);
but when scrolling down or up it runs the useEffect again
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
