Optimizing React Native FlatList for Large Data Sets
Learn how to keep FlatList fast and memory‑efficient by using keyExtractor, getItemLayout, memoized rows, and the right initial render settings. Avoid common pitfalls that cause jank or memory spikes.
03 Apr 2026, 02:25 UTC

Why FlatList is the go‑to for large lists
When you need to display hundreds or thousands of items, the default ScrollView will quickly exhaust memory because it renders every child. FlatList solves this by rendering only the rows that are currently visible plus a small buffer. This virtualization keeps the app responsive on both iOS and Android.
Key props that drive performance
| Prop | Purpose | Typical Value |
|---|---|---|
keyExtractor | Provides a stable, unique key for each item. | item => item.id.toString() |
getItemLayout | Pre‑calculates item height/offset for fixed‑size rows. | See example below. |
initialNumToRender | Number of items rendered on mount. | 10–20 for long lists. |
maxToRenderPerBatch | Items rendered per batch during scroll. | 5–10. |
windowSize | Number of viewports kept in memory. | 7 (default). |
removeClippedSubviews | Unmounts items outside the viewport. | True for large lists; test on Android. |
Concrete example: a memoized list of 1,000 products
import React, { memo } from 'react';
import { FlatList, View, Text, StyleSheet } from 'react-native';
// A stable key extractor
const keyExtractor = (item) => item.id.toString();
// For fixed‑height items (e.g., 80px)
const getItemLayout = (data, index) => ({
length: 80,
offset: 80 * index,
index,
});
// Memoized row component to avoid re‑renders when list state changes
const ProductRow = memo(({ item }) => (
{item.title}
${item.price}
));
const ProductList = ({ data }) => (
}
// Pull‑to‑refresh support
refreshing={false}
onRefresh={() => {/* refresh logic */}}
// Infinite scroll
onEndReachedThreshold={0.5}
onEndReached={() => {/* load more data */}}
/>
);
const styles = StyleSheet.create({
row: { height: 80, flexDirection: 'row', justifyContent: 'space-between', padding: 10, borderBottomWidth: 1, borderColor: '#ccc' },
price: { fontWeight: 'bold' },
});
Run this on React Native 0.70+ and enable the performance monitor (shake → “Show FPS”). You should see a steady 60 fps even when scrolling through 1,000 items.
Common pitfalls and how to avoid them
- Missing
keyExtractor: React will warn about duplicate keys and may reuse views incorrectly, causing flicker. - Using the array index as key: If the list is reordered or items are inserted/deleted, the index changes and state inside rows can be lost.
- No
getItemLayoutfor long lists: Without it, FlatList measures each row on the fly, which can freeze the UI for 1000+ items. - Setting
initialNumToRendertoo high: Rendering 100 items on mount will delay startup on low‑end devices. - Not memoizing row components: A state change in the parent (e.g., a search filter) forces all rows to re‑render, dropping FPS.
- Over‑using
removeClippedSubviews: On Android, this can clip elements that useposition: absoluteorzIndex. Test on both platforms.
Diagnosing performance issues
- Open Flipper and attach the React DevTools profiler. Verify that only the visible rows are mounted.
- Check the console for warnings about duplicate keys or missing
keyExtractor. - Use the “Measure” tool in Flipper to confirm that
getItemLayoutis being used (no “measure” calls). - Profile memory in Android Studio Profiler or Xcode Instruments while scrolling. A healthy list should keep memory usage stable.
When FlatList is not enough
For lists that exceed 10,000 items or require complex grouping, consider SectionList or a third‑party virtualization library like react-native-reanimated with VirtualizedList. However, for most use cases, a well‑configured FlatList will deliver the performance you need.
Practical checklist before shipping
- Ensure
keyExtractoris stable and unique. - Provide
getItemLayoutif items have a fixed height. - Set
initialNumToRenderto 10–20. - Memoize row components or use
React.memo. - Test on both iOS and Android, especially with
removeClippedSubviews. - Use Flipper to confirm only visible rows are mounted.
- Monitor FPS and memory during realistic scrolling patterns.
Following this guide will help you ship a smooth, responsive list experience in React Native, even with thousands of items.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.