Difference between FlatList and VirtualizedList - react-native

I am new in react native, and am confused about the difference between FlatList and VirtualizedList.
So,
What are the differences between FlatList and VirtualizedList ?
When should I use each ?

The <FlatList> is a performant interface for rendering basic, flat lists.
On the other side, the <VirtualizedList> is a base implementation of the <FlatList> and <SectionList> components, which are also better documented. In general, <VirtualizedList> should only really be used if you need more flexibility than FlatList provides, e.g. for use with immutable data instead of plain arrays.
FlatList example:
const App = () => {
const renderItem = ({ item }) => (
<Item title={item.title} />
);
return (
<SafeAreaView style={styles.container}>
<FlatList
data={DATA}
renderItem={renderItem}
keyExtractor={item => item.id}
/>
</SafeAreaView>
);
}
VirtualizedList example:
const App = () => {
return (
<SafeAreaView style={styles.container}>
<VirtualizedList
data={DATA}
initialNumToRender={4}
renderItem={({ item }) => <Item title={item.title} />}
keyExtractor={item => item.key}
getItemCount={getItemCount}
getItem={getItem}
/>
</SafeAreaView>
);
}
More info:
https://reactnative.dev/docs/virtualizedlist
https://reactnative.dev/docs/flatlist

Related

How to get current active index of FlatList in Reract Native?

I have below simple FlatList:
<FlatList
data={Images}
renderItem={({item}) => <Item item={item} />}
keyExtractor={item => item.index}
horizontal
showsHorizontalScrollIndicator={false}
pagingEnabled
onScroll={onScroll}
decelerationRate={-100000000000000}
scrollEventThrottle={16}
/>
How to get current active index of the FlatList as switching between different list item?
You can pass a callback to the onViewableItemsChanged prop to accomplish this.
const onViewableItemsChanged = ({ viewableItems, changed }) => {
console.log(viewableItems);
console.log(changed);
};
// ...
<FlatList
// ...
onViewableItemsChanged={onViewableItemsChanged}
/>
Docs here: https://reactnative.dev/docs/flatlist#onviewableitemschanged
Blog post with example: https://thewebdev.info/2022/02/19/how-to-get-the-index-of-the-currently-visible-item-in-a-react-native-flat-list/

How to fix error VirtualizedLists should never be nested inside plain ScrollViews with the same orientation?

My application has the error "VirtualizedLists should never be nested inside plain ScrollViews with the same orientation because it can break windowing and other functionality - use another VirtualizedList-backed container instead.", but I don't know how to solve it. In ScrollView I have two Flatlists and a header.
Screen: Flatlists inside my ScrollView
My code:
const renderItem = ({ item }) => <AssuntoCard item={item} />;
return (
<Container> // SCROLLVIEW
<TouchableOpacity
>
<Close />
</TouchableOpacity>
<Titulo>
<Bold>O que vocĂȘ deseja</Bold>
{"\n"}estudar hoje?
</Titulo>
<Subtitulo>Selecione um capĂ­tulo: </Subtitulo>
<Linhas> // View with two columns
<Colunas> // Column 1 for even items
<FlatList
scrollEnabled={false}
data={card.filter((item) => item.id % 2 == 0)}
renderItem={renderItem}
keyExtractor={(item) => item.id}
/>
</Colunas>
<Colunas> // Column 2 for odd items
<FlatList
scrollEnabled={false}
data={card.filter((item) => item.id % 2 !== 0)}
renderItem={renderItem}
keyExtractor={(item) => item.id}
/>
</Colunas>
</Linhas>
<Modal>
// ...
</Modal>
</Container>
);

Last item in React native flat list goes beyond screen

I have a flatlist with some styles on the outer containers as follows.
<View style={containerStyle}>
// more jsx components come here
<View style={resultContainerStyle}>
<FlatList
data={results}
keyExtractor={(item) => (item.id && item.id.toString())}
renderItem={({ item, index }) => (
<ListItem
item={item}
selectItem={selectItem}
/>
)}
/>
</View>
</View>
The issue is that the last values of the list go beyond the view of the screen and there is no way to view it unless a fixed height is put on the parent container. Is it possible to do this without a fixed height.
A SafeAreaView can be used to limit the view to the "safe" areas of the screen(avoiding the notch and curved bottom. Checkout the following example
<SafeAreaView style={containerStyle}>
// more jsx components come here
<View style={resultContainerStyle}>
<FlatList
data={results}
keyExtractor={(item) => (item.id && item.id.toString())}
renderItem={({ item, index }) => (
<ListItem
item={item}
selectItem={selectItem}
/>
)}
/>
</View>
</SafeAreaView>
more examples can be found at the react native docs.

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 render a zero state when data is empty

Is it possible to render an alternate component when the data is empty? The only reason I would not just render the list or not render the list is that the ListHeaderComponent is necessary in both scenarios (data.length and !data.length)...
const data = []
<FlatList
contentContainerStyle={styles.list}
data={data} // if empty or !data.length render <ZeroComponent/>
UPDATE
react-native recently added ListEmptyComponent
const data = []
_listEmptyComponent = () => {
return (
<View>
// any activity indicator or error component
</View>
)
}
<FlatList
data={data}
ListEmptyComponent={this._listEmptyComponent}
contentContainerStyle={styles.list}
/>
const data = []
renderFooter = () => {
if (data.length != 0) return null;
return (
<View>
// any activity indicator or error component
</View>
);
};
<FlatList
contentContainerStyle={styles.list}
data={data}
ListFooterComponent={this.renderFooter}
/>
Hope this helps
There is a prop ListEmptyComponent which can do the job.
<FlatList
data={this.state.data}
renderItem={this.renderItem}
keyExtractor={(item, index) => item.id}
ListHeaderComponent={this.showFilters()}
ListEmptyComponent={this.showEmptyListView()}
/>
You can do something like this
{data.length > 0 ? <FlatList ... /> : <EmptyList />}
Hope it helps