I have a list of 300 items. I'm using FlatList to render the items.
ISSUE:
I tried to optimise the list by tweaking the windowSize
, maxToRenderPerBatch
but the issue still persist.
You can check the code in below sandbox link.
Thankyou in advance !
https://codesandbox.io/s/gracious-dhawan-i4d51h?file=/src/App.js
Below is the code snippet
const data = [
{
id: 1,
first_name: "Shaina",
last_name: "Osorio",
email: "sosorio0@a8.net"
},
{
id: 2,
first_name: "Ania",
last_name: "Cotilard",
email: "acotilard1@about.me"
},
{
id: 3,
first_name: "Hagen",
last_name: "Lisciandri",
email: "hlisciandri2@nature.com"
}
]
const isEqual = (prev, next) => { return true; }; const RenderItem = React.memo((props) => { const { id, first_name, email } = props; console.log("id >>> ", id); return ( <View style={{ padding: 5, backgroundColor: "lightblue", marginVertical: 3 }} > <Text>First Name: {first_name}</Text> <Text>Email: {email}</Text> </View> ); }, isEqual); function App() { return ( <View style={{ flex: 1 }}> <FlatList data={data} renderItem={({ item }) => ( <RenderItem id={item.id} first_name={item.first_name} email={item.email} /> )} initialNumToRender={15} maxToRenderPerBatch={15} keyExtractor={(item) => item.id} /> </View> ); } export default App;
In your example, you are logging inside your renderItem, so when a new element comes into the rendered area, it is logged. This happens when you scroll. But this doesn't mean that the whole list will be re-rendered. Just place a conosle.log directly in the component that hosts the list, and you'll see that it's only rendered once, unlike the renderItem, which is rendered every time a new item is created by a scroll.
const App = ()=> {
console.log("Entire List Rerendered");
return (
<View style={{ flex: 1 }}>
<FlatList
data={data}
renderItem={rendering}
initialNumToRender={5}
maxToRenderPerBatch={5}
keyExtractor={(item) => item.id}
/>
</View>
);
}
Flashlist might help, because it recycles renderItems and doesn't destroy them like Flatlist does. But you should test that better.
Can you define it as a separate function
const rendering = ({ item }) => {
return (
<RenderItem
id={item.id}
first_name={item.first_name}
email={item.email}
/>
)
}
and then call it on your flat list?
<FlatList
data={data}
renderItem={rendering}
initialNumToRender={15}
maxToRenderPerBatch={15}
keyExtractor={(item) => item.id}
/>
Inline event handlers are anonymous functions. They are created every time the component renders.
UPDATE
Extract your render and keyExtractor functions and surround them with useCallback like that
function App() {
const rendering = useCallback(({item}) => {
console.log("id >>> ", item.id);
return (
<View
style={{
padding: 5,
backgroundColor: "lightblue",
marginVertical: 3
}}
>
<Text>First Name : {item.first_name}</Text>
<Text>Email : {item.email}</Text>
</View>
)
}, []);
const keyExtractoring = useCallback((item) => {
return item.id.toString();
}, []);
return (
<View style={{ flex: 1 }}>
<FlatList
data={data}
renderItem={rendering}
initialNumToRender={5}
maxToRenderPerBatch={5}
keyExtractor={keyExtractoring}
/>
</View>
);
}
Check out FlashList by Shopify they are saying that it is much more optimized than Flatlist. maybe it can meet your needs. no harm in trying: Click Here
import React from "react";
import { View, Text, StatusBar } from "react-native";
import { FlashList } from "@shopify/flash-list";
const DATA = [
{
title: "First Item",
},
{
title: "Second Item",
},
];
const MyList = () => {
return (
<FlashList
data={DATA}
renderItem={({ item }) => <Text>{item.title}</Text>}
estimatedItemSize={200}
/>
);
};
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.