Stop Using ScrollView for Long Lists: Optimizing React Native FlatList
Learn how to move from ScrollView to FlatList in React Native to handle long datasets. We cover virtualization, getItemLayout, and memory management tips.
23 Sept 2026, 19:37 UTC

The Memory Wall in List Rendering
When building a mobile feed or a long directory, the instinct is often to wrap a map function inside a ScrollView. While this works for ten items, it fails at one hundred. Because ScrollView renders every child component immediately upon mounting, your application's memory heap grows linearly with your data. On low‑end devices, this leads to sluggish interactions or immediate crashes.
FlatList solves this with virtualization—only the items visible on screen (plus a small buffer) are kept in memory. As the user scrolls, off‑screen items are unmounted and new ones are mounted.
Reducing Calculation Overhead with getItemLayout
By default, FlatList must measure each item to compute scroll positions, which can stall fast scrolling. If your items have a fixed height, skip this step with getItemLayout, which tells the list the exact start and end of each item.
Example: Fixed‑Height Implementation
import React from 'react';
import { FlatList, Text, View, StyleSheet } from 'react-native';
const ITEM_HEIGHT = 70;
const DataList = ({ data }) => {
const renderItem = ({ item }) => (
{item.title}
);
return (
item.id.toString()}
getItemLayout={(data, index) => ({
length: ITEM_HEIGHT,
offset: ITEM_HEIGHT * index,
index,
})}
initialNumToRender={10}
windowSize={5}
/>
);
};
const styles = StyleSheet.create({
item: {
height: ITEM_HEIGHT,
justifyContent: 'center',
padding: 20,
borderBottomWidth: 1,
borderColor: '#ccc',
},
});
Tuning the Virtualization Window
- initialNumToRender: How many items are rendered on the first paint. A high value delays the initial view; a low value can leave a brief blank before items appear.
- windowSize: Number of viewports rendered beyond the visible area. A larger window reduces blank gaps during rapid scrolling but consumes more memory.
Avoiding Common Performance Traps
Defining renderItem as an anonymous function inside the FlatList causes a new function on every parent render, potentially triggering a full list re‑render. Use a memoized or external function instead.
// BAD
<FlatList
renderItem={({ item }) => <MyComponent data={item} />}
...
/>
Trade‑offs and Limitations
Virtualization helps with memory, but if items are heavy—nested lists, large images, or complex animations—the mounting/unmounting cost can still cause frame drops. In those cases, consider simplifying item layout or using RecyclerListView for even tighter control.
Verification Checklist
- Memory Leak Check: Use Flipper or React Native Debugger to watch the heap. If it climbs steadily as you scroll, verify
keyExtractorstability. - Frame Rate Check: Enable the built‑in Perf Monitor. Compare FPS with and without
getItemLayout. - Mounting Check: Add
console.loginsiderenderItem. You should see logs appear/disappear as items mount/unmount.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.