Cheat Sheets

React Native FlatList Cheat Sheet: keyExtractor, renderItem & Performance

By ArpaNeuro Team September 17, 2026
React Native FlatList cheat sheet

FlatList virtualizes rows: it mounts views near the viewport instead of every item at once. You must provide stable keyExtractor ids and a lightweight renderItem. For very large or nested lists, consider FlashList. Never replace FlatList with .map inside ScrollView for long data.

This React Native cheat sheet is written for people searching for a fast, accurate reference: students, junior developers, and teams shipping production software. Pin it, copy the snippets, and come back when syntax slips.

Quick reference

  • data: An array. Changing identity every render resets scroll unless you are careful.
  • renderItem: ({ item, index }) => element. Extract Item components and wrap with memo if they re-render too often.
  • keyExtractor: Stable unique strings. Do not use index if the list can reorder or insert.
  • extraData: Pass state the row needs that is not in item so the list knows to refresh.
  • windowSize / maxToRenderPerBatch: Tune when profiling says so — not as a first superstition.
  • getItemLayout: If every row is the same height, skip measurement for faster jumps.
  • onEndReached: Infinite scroll. Guard with a loading flag so you do not double-fetch.
  • ListHeader / Empty: ListHeaderComponent, ListEmptyComponent instead of wrapping the list in extra ScrollViews.

Copy-paste examples

Paged list with memoized rows

Keep renderItem stable. onEndReachedThreshold is a fraction of the visible length.

import { memo, useCallback, useState } from 'react';
import { FlatList, Text, View } from 'react-native';

const Row = memo(function Row({ title }) {
  return <Text style={{ padding: 16 }}>{title}</Text>;
});

export function Feed({ pages, onMore }) {
  const [busy, setBusy] = useState(false);
  const renderItem = useCallback(({ item }) => <Row title={item.title} />, []);
  return (
    <FlatList
      data={pages}
      keyExtractor={(item) => String(item.id)}
      renderItem={renderItem}
      onEndReached={() => {
        if (busy) return;
        setBusy(true);
        Promise.resolve(onMore()).finally(() => setBusy(false));
      }}
      onEndReachedThreshold={0.4}
      ListEmptyComponent={<View><Text>No items</Text></View>}
    />
  );
}

Common mistakes

  • Using index as key on a feed that prepends items.
  • Putting a FlatList inside a ScrollView (nested virtualization, broken windowing).
  • Inline renderItem={() => ...} that closes over changing state and re-creates every row.
  • Anonymous objects in style plus heavy work in render for every visible row.

FAQ

  1. FlatList or SectionList? SectionList for grouped headers (contacts). FlatList for a single array. FlashList if you profile and still jank.
  1. Why is my list blank? Parent without flex: 1, or a bounded height. Lists need a finite height to virtualize.
  1. How do I pull to refresh? refreshing + onRefresh props on FlatList. Keep that boolean in state.

Related React Native cheat sheets

Build with this stack

When a cheat sheet is not enough — you need a production app, a student FYP, or a custom dashboard — ArpaNeuro builds mobile app development and also sells ready-made source code. Request a quote and tell us the stack.

Browse software development services or the source code marketplace if you want a working codebase instead of starting from a blank file.

← All Articles Get a Quote →