I'm trying to make a video and photo feed, for that I use the flatlist tool and an event card component. I can visualize my videos. But it is not optimized. And I have this problem.
VirtualizedList: You have a large list that is slow to update - make sure your renderItem function renders components that follow React performance best practices like PureComponent, shouldComponentUpdate, etc. {"contentLength": 3816, "dt": 3686, "prevDt": 936}
myFlatlist
const EVENTS = graphql(
`
query events {
events {
id
category
description
name
file {
url
}
author {
username
avatar {
url
}
}
}
}
`
);
export default function ReelForyouScreen({
navigation,
}: RootTabScreenProps<"Foryou">) {
const { loading, error, data } = useQuery(EVENTS);
const [focusedIndex, setFocusedIndex] = React.useState(0);
const handleScroll = React.useCallback(
({
nativeEvent: {
contentOffset: { y },
},
}: NativeSyntheticEvent<NativeScrollEvent>) => {
const offset = Math.round(y / 500);
setFocusedIndex(offset);
},
[setFocusedIndex]
);
const verification = (event: Event, index: int) => {
const parts: string[] = event?.file.url.split(".");
const extension: string = parts[parts.length - 1];
if (extension === "mp4") {
return <EventCard event={event} shouldPlay={focusedIndex === index} />;
} else {
return <EventCardPhoto event={event} />;
}
};
return (
<Box bg={loading ? "#000" : "#000"}>
<FlatList
py={4}
mx={1}
removeClippedSubviews
initialNumToRender={5}
maxToRenderPerBatch={10}
windowSize={10}
refreshing={loading}
onScroll={handleScroll}
data={data?.events as Event[]}
renderItem={({ item, index }) => verification(item, index)}
/>
</Box>
);
}
and my component
type Props = {
event: Event;
shouldPlay: boolean;
imageState?: StateModifier<string | null>;
};
const EventCard = ({ event, shouldPlay }: Props) => {
const [liked, setLiked] = useState(false);
const handlePress = () => {
setLiked(!liked);
};
const video = useRef<Video>(null);
const [isLoading, setIsLoading] = useState(true);
const onVideoLoad = () => {
setIsLoading(false);
};
const reel = {
reelimage:
"https://weezevent.com/wp-content/uploads/2019/03/01184934/organiser-soiree.jpeg",
username: "Matteo.hmi",
evenements: "11",
date: "2023-04-02T08:02:17-05:00",
followers: "255",
userimage:
"https://media.licdn.com/dms/image/D5603AQEh2KcqHOfMgw/profile-displayphoto-shrink_800_800/0/1666676898390?e=2147483647&v=beta&t=x88KFJJJJOLex9X3XQTwaEs-2KCodrovN76Mp6ZsKC0",
numberLike: "255",
numberComment: "355",
numberShare: "50",
numberTicketDisponible: "20",
reelDescription:
"Ne ratez pas le prochain évènement de l’Arc Paris ce samedi à 10:00 PM.",
};
const iconsInteraction: { name: string; iconLibrary: any; type: any }[] = [
{
name: "chatbubble-ellipses",
iconLibrary: MaterialCommunityIcons,
type: reel.numberComment,
},
{ name: "arrow-redo", iconLibrary: Ionicons, type: reel.numberShare },
{
name: "bookmark",
iconLibrary: Fontisto,
type: reel.numberTicketDisponible,
},
];
return (
<Box
rounded="3xl"
bg="transparent"
h={500}
shadow={3}
mb={8}
overflow="hidden"
>
{isLoading && (
<Box
w="100%"
h="100%"
bg="black"
alignItems="center"
justifyContent="center"
>
<ActivityIndicator size="large" color="#fff" />
</Box>
)}
<Video
ref={video}
source={{
uri: event?.file.url,
}}
style={{
width: "100%",
height: "100%",
position: "absolute",
}}
useNativeControls={false}
isLooping
onLoad={onVideoLoad}
resizeMode="cover"
usePoster
posterSource={{
uri: event?.file.url,
}}
shouldPlay={shouldPlay}
on
isMuted={false}
/>
<VStack h="100%" justifyContent="space-between">
<Pressable
style={{ alignSelf: "flex-start", paddingTop: 18, paddingLeft: 18 }}
>
<HStack space={2} alignItems="center">
<Avatar
size={10}
source={{
uri:
event?.author.avatar === null
? "https://media.licdn.com/dms/image/C4D03AQHsbDsDTukBaw/profile-displayphoto-shrink_400_400/0/1632175934748?e=1684972800&v=beta&t=JIsEqBO-2kmrjeS8BC9xGx8EfU4Bshbn99D3nGALV64"
: event?.author.avatar?.url,
}}
/>
<Text color="white" fontWeight="blod">
{event?.author.username}
</Text>
</HStack>
</Pressable>
<VStack space={16} px={18}>
<VStack alignSelf="flex-end" space={1}>
<Pressable alignItems="center" onPress={handlePress}>
<Animatable.View
animation={liked ? "rubberBand" : ""}
style={{ width: "100%", alignItems: "center" }}
>
<Ionicons
alignSelf="center"
name="heart"
size={40}
color={liked ? "#ff2d55" : "white"}
onpPress={handlePress}
/>
</Animatable.View>
</Pressable>
{iconsInteraction.map((icon, index) => (
<Container flexDirection="column" alignItems="center" key={index}>
<Icon as={Ionicons} name={icon.name} size={8} color="white" />
<Text color="white" fontWeight="bold">
{icon.type}
</Text>
</Container>
))}
</VStack>
<Box bottom={6} left={4} shadow={1}>
<Text color="white" fontSize={15} fontWeight="bold">
{event?.description}
</Text>
</Box>
</VStack>
</VStack>
</Box>
);
};
export default memo(EventCard);
I would like it to work in an optimal way but I can't.
Try FlashList from shopify, they created a new FlatList with a better optimization.