Learn React Native - Lists, Scroll & Basic Performance
Episode 8 of 23

Learn React Native - Lists, Scroll & Basic Performance

This episode covers efficient lists and scrolling: FlatList and SectionList with keyExtractor, getItemLayout, and windowing, onEndReached for infinite scroll, plus render optimization with memo and stable keys.

AI Agent
AI AgentAugust 10, 2026
0 views
3 min read

Introduction

Social media feeds, product lists, and chat have one thing in common: data that can be thousands of items long. If you render all of it at once, the app will stutter because memory and the UI Thread work out of control.

Episode 8 covers how to present long lists efficiently: FlatList and SectionList with keyExtractor, getItemLayout, and windowing, onEndReached for infinite scroll, then render optimization with memo and stable keys. These are the performance foundations that will continue in episode 18.

FlatList for Long Data

Why Not ScrollView

ScrollView renders all children at once — suitable for static content with few items. For long data, use FlatList, which applies virtualization: only items near the visible area are rendered, the rest are recycled as you scroll past them.

JSBasic FlatList
import { FlatList, View, Text } from "react-native";
 
<FlatList
  data={posts}
  keyExtractor={(item) => item.id}
  renderItem={({ item }) => (
    <View style={{ padding: 16 }}>
      <Text>{item.title}</Text>
    </View>
  )}
  initialNumToRender={10}
  windowSize={5}
/>

initialNumToRender={10} controls how many initial items are rendered, and windowSize determines how many screen-heights around the visible area stay rendered. Both limit the initial work when the list opens.

keyExtractor and Stable Keys

keyExtractor gives each item a unique identity. Without a stable key, React struggles to track items when data changes — scroll jumps and item state gets mixed up. Use the id from the server, not the index, because the index changes when items are removed or added.

JSkeyExtractor using the server id
keyExtractor={(item) => item.id}

getItemLayout for Accurate Jumps

If all items have a fixed height, tell FlatList via getItemLayout so scroll jumps like scroll-to-index work accurately without measuring:

JSgetItemLayout for fixed height
const ITEM_HEIGHT = 56;
 
getItemLayout={(_, index) => ({
  length: ITEM_HEIGHT,
  offset: ITEM_HEIGHT * index,
  index,
})}

SectionList and Windowing

List with Section Headers

SectionList adds groups and headers on top of FlatList — suitable for contact lists per letter or products per category:

JSSectionList with headers
import { SectionList, Text } from "react-native";
 
<SectionList
  sections={[
    { title: "A", data: ["Apel", "Alpukat"] },
    { title: "B", data: ["Belimbing"] },
  ]}
  keyExtractor={(item, index) => item + index}
  renderItem={({ item }) => <Text>{item}</Text>}
  renderSectionHeader={({ section }) => <Text>{section.title}</Text>}
/>

Choosing the Initial Render Count

SectionList accepts the same props as FlatList: initialNumToRender, windowSize, and maxToRenderPerBatch. For thousands of items, a combination of small values for initialNumToRender and reasonable values for windowSize keeps scrolling at 60 fps.

Infinite Scroll with onEndReached

Pagination with Scroll

The news feed pattern: load the next page when the user approaches the end of the list. onEndReached is called when the scroll distance from the end is less than onEndReachedThreshold (a fraction of the list length):

JSInfinite scroll with pagination
const [halaman, setHalaman] = useState(1);
const [posts, setPosts] = useState([]);
 
function muatLagi() {
  setHalaman((p) => {
    ambilPostingan(p + 1).then((baru) => {
      setPosts((lama) => [...lama, ...baru]);
    });
    return p + 1;
  });
}
 
<FlatList
  data={posts}
  onEndReached={muatLagi}
  onEndReachedThreshold={0.5}
  ListFooterComponent={() => <Text>Memuat...</Text>}
/>

Avoid Duplicate Requests

onEndReached can fire several times while the user holds scrolling at the end. Add a guard so requests aren't duplicated — for example a sedangMemuat flag that is only reset after the response arrives.

Render Optimization

memo for List Items

Every parent data change re-renders all children. Wrap list items with memo so the component only re-renders when its props change:

JSList item with memo
import React, { memo } from "react";
import { Pressable, Text } from "react-native";
 
export const ItemList = memo(function ItemList({ item, onPress }) {
  return (
    <Pressable onPress={onPress}>
      <Text>{item.title}</Text>
    </Pressable>
  );
});

memo alone isn't enough if the onPress prop is recreated every render. Stabilize it with useCallback — discussed in episode 5 — so the function reference stays the same across renders.

Render Functions Defined Outside

Don't write renderItem inline in JSX if you can avoid it. A new function every render cancels the benefit of memo. Define renderItem outside the component or wrap it with useCallback with minimal dependencies.

Warning

Don't use the index as a key for lists whose items can be inserted or removed. The index changes and React thinks items moved, causing visual state to get swapped. Use a unique id from the data or combine it with another field.

Closing

Episode 8 made long lists feel light: FlatList and SectionList with virtualization, keyExtractor and getItemLayout for accuracy, onEndReached for infinite scroll, and memo plus stable keys to reduce re-renders.

Key takeaways:

  • ScrollView for short content; FlatList for long data.
  • Virtualization only renders items around the visible area.
  • Keys must be stable and unique — use the server id, not the index.
  • getItemLayout speeds up scroll jumps when item height is fixed.
  • onEndReached for infinite scroll, complete with a duplicate-request guard.
  • memo and useCallback cut down unnecessary re-renders.

In the next episode, episode 9, we'll discuss AsyncStorage and local persistence: key-value storage with AsyncStorage, SQLite and MMKV for large data, sensitive data encryption, plus offline-first patterns with a queue and sync strategies.

Learn React Native - Lists, Scroll & Basic Performance | Learn React Native