FlatList is the main React Native component for displaying high-performance lists with element virtualization. Unlike ScrollView, FlatList renders only the visible screen elements, saving memory and CPU. The component supports horizontal and vertical scrolling, pull-to-refresh, and infinite loading. Read more about list architecture in Meta's documentation.
Key Takeaways
FlatList is a React Native component that implements a virtualized list with high-performance rendering of large data sets. The component is built on top of VirtualizedList and provides a declarative API for creating flat lists of any complexity.
FlatList was introduced in React Native 0.43 as a replacement for the deprecated ListView. According to Meta (2026), FlatList is used in 85% of React Native applications that work with lists. The component supports all common scenarios: contacts, news feeds, product catalogs, and chats.
Before FlatList, developers used ListView, which required manual cell reuse configuration. FlatList automated this process by implementing windowed rendering similar to RecyclerView in Android (2014) and UICollectionView in iOS (2012). In modern projects, FlatList is the de facto standard for any list implementation.
FlatList virtualization is a mechanism where the component renders only the elements that fall within the visible screen area, plus a small buffer on each side. The remaining elements are not created in the DOM, saving memory and speeding up rendering.
When scrolling, FlatList reuses already created View cells, replacing their data. This prevents creating thousands of Views for a list of 10,000 elements. The default buffer size is 10 elements above and below the visible area, but it is configurable via windowSize.
| Parameter | Default | Description |
|---|---|---|
| windowSize | 21 | Number of pages to render (1 page = screen height) |
| initialNumToRender | 10 | Number of elements on the first render |
| maxToRenderPerBatch | 10 | Maximum elements rendered per batch |
| removeClippedSubviews | false | Remove Views outside the screen from the hierarchy |
Optimal configuration of these parameters allows balancing between scroll smoothness and memory consumption. For lists with large elements, it is recommended to reduce windowSize to 5-7.
FlatList API includes a set of props for configuring the list display and behavior. The two required props are data (data array) and renderItem (element rendering function). keyExtractor improves performance by providing a unique key for each element.
import React from 'react';
import { FlatList, View, Text, StyleSheet } from 'react-native';
const App = () => {
const data = Array.from({ length: 100 }, (_, i) => ({
id: i.toString(),
title: `Item #${i + 1}`,
}));
return (
<FlatList
data={data}
renderItem={({ item }) => (
<View style={styles.item}>
<Text>{item.title}</Text>
</View>
)}
keyExtractor={item => item.id}
ItemSeparatorComponent={() => <View style={styles.separator} />}
/>
);
};ItemSeparatorComponent adds a separator between elements, ListHeaderComponent and ListFooterComponent add header and footer to the list. This allows creating complex layouts without additional wrappers.
const styles = StyleSheet.create({
item: {
padding: 16,
backgroundColor: '#fff',
borderBottomWidth: 1,
borderBottomColor: '#e0e0e0',
},
separator: {
height: 1,
backgroundColor: '#ccc',
},
});FlatList optimization is critical for applications with hundreds and thousands of elements. Without proper configuration, the list may lag during scrolling, consume excessive memory, and cause crashes on low-end devices.
The first rule is to use keyExtractor with unique and stable identifiers. Using indices as keys leads to incorrect cell reuse and state bugs. The second rule is to wrap renderItem in useCallback and use React.memo for the item component.
If all elements have the same height, getItemLayout allows FlatList to calculate the scroll position without measuring components. This provides a significant performance boost, especially when scrolling to a specific index.
const ITEM_HEIGHT = 80;
const getItemLayout = (data, index) => ({
length: ITEM_HEIGHT,
offset: ITEM_HEIGHT * index,
index,
});
<FlatList
data={data}
getItemLayout={getItemLayout}
renderItem={renderItem}
/FlatList>useMemo for data prevents unnecessary re-renders. If data comes from an API, transform it once and cache it. Use React.memo for the item component to avoid rendering unchanged elements.
Horizontal FlatList is created by adding the prop horizontal={true}. The list changes the scroll direction to the X axis, which is convenient for product carousels, image galleries, and horizontal menus.
In horizontal mode, it is important to correctly configure snapToInterval and snapToAlignment for step-by-step scrolling like in native carousels. The component automatically handles momentum and finger release, stopping at the nearest element.
<FlatList
horizontal
data={images}
renderItem={renderItem}
keyExtractor={item => item.id}
showsHorizontalScrollIndicator={false}
snapToInterval={CARD_WIDTH + GAP}
snapToAlignment="start"
decelerationRate="fast"
pagingEnabled
onViewableItemsChanged={onViewableItemsChanged}
/>onViewableItemsChanged is a callback triggered when visible elements change. It is used for analytics, lazy image loading, and activating videos only for visible cards.
Pull-to-refresh in FlatList is implemented via the refreshing and onRefresh props, working together with a loading state. When pulling the list down, onRefresh is called, and the refreshing flag blocks repeated calls.
Infinite scroll is configured via onEndReached — a callback triggered when approaching the end of the list. onEndReachedThreshold determines how many elements before the end the event fires. Cursor-based pagination is typically used.
const ListWithPagination = () => {
const [data, setData] = React.useState([]);
const [page, setPage] = React.useState(1);
const [refreshing, setRefreshing] = React.useState(false);
const loadMore = React.useCallback(async () => {
const newData = await fetchPage(page);
setData(prev => [...prev, ...newData]);
setPage(p => p + 1);
}, [page]);
return (
<FlatList
data={data}
renderItem={renderItem}
keyExtractor={item => item.id}
refreshing={refreshing}
onRefresh={loadMore}
onEndReached={loadMore}
onEndReachedThreshold={0.5}
/>
);
};Important: onEndReached may be called multiple times. Add an isLoading flag to block repeated requests until the previous one completes. Use ActivityIndicator in ListFooterComponent to indicate loading.
Frequently Asked Questions
FlatList uses virtualization — it renders only visible elements, saving memory with large data sets. ScrollView renders all children at once, suitable only for small lists of 20-30 elements. FlatList is optimal for 100+ elements.
Flashing occurs when the reference to the data array changes. Use extraData passing the dependency, or wrap renderItem in React.memo. For full control, use useMemo to stabilize data references.
FlatList is not designed to be nested inside ScrollView due to gesture conflicts. Solutions: use FlatList with nestedScrollEnabled (Android), SectionList for sections, or move external scrolling to FlatList via ListHeaderComponent.
Use the Animated API inside renderItem with a delay based on index. For scrolling, use onViewableItemsChanged to trigger animations. Libraries like react-native-reanimated and react-native-lottie simplify creating complex appearance animations.
VirtualizedList is the base virtualization component on which FlatList and SectionList are built. FlatList is a wrapper around VirtualizedList with a simplified API for flat lists. VirtualizedList provides lower-level control but is rarely used directly.
Summary
We will develop a mobile application turnkey
IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.
Read also