FlatList renders only visible items, making it essential for long lists. Never use ScrollView with hundreds of items.

Basic FlatList

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

const DATA = [
    { id: '1', title: 'First Item' },
    { id: '2', title: 'Second Item' },
    { id: '3', title: 'Third Item' },
];

function ItemList() {
    return (
        <FlatList
            data={DATA}
            keyExtractor={(item) => item.id}
            renderItem={({ item }) => (
                <View style={{ padding: 16, borderBottomWidth: 1, borderColor: '#eee' }}>
                    <Text>{item.title}</Text>
                </View>
            )}
        />
    );
}
  

renderItem Props

Each item receives item, index, and separators:

  renderItem={({ item, index }) => (
    <Text>{index + 1}. {item.title}</Text>
)}
  

Extract to a separate component for performance:

  const ListItem = React.memo(({ item }) => (
    <Text>{item.title}</Text>
));

<FlatList
    data={DATA}
    renderItem={({ item }) => <ListItem item={item} />}
    keyExtractor={(item) => item.id}
/>
  

Pull to Refresh

  function RefreshableList() {
    const [data, setData] = useState(DATA);
    const [refreshing, setRefreshing] = useState(false);

    const onRefresh = async () => {
        setRefreshing(true);
        const newData = await fetchItems();
        setData(newData);
        setRefreshing(false);
    };

    return (
        <FlatList
            data={data}
            renderItem={({ item }) => <ListItem item={item} />}
            keyExtractor={(item) => item.id}
            refreshing={refreshing}
            onRefresh={onRefresh}
        />
    );
}
  

Infinite Scroll

Load more data when the user reaches the bottom:

  <FlatList
    data={data}
    renderItem={renderItem}
    keyExtractor={(item) => item.id}
    onEndReached={loadMore}
    onEndReachedThreshold={0.5}
    ListFooterComponent={loading ? <ActivityIndicator /> : null}
/>
  

List Header and Empty State

  <FlatList
    data={data}
    renderItem={renderItem}
    keyExtractor={(item) => item.id}
    ListHeaderComponent={<Text style={{ fontSize: 20, padding: 16 }}>My Items</Text>}
    ListEmptyComponent={<Text style={{ textAlign: 'center', padding: 32 }}>No items found</Text>}
    ItemSeparatorComponent={() => <View style={{ height: 1, backgroundColor: '#eee' }} />}
/>
  

Performance Tips

  • Always provide keyExtractor
  • Use React.memo on list item components
  • Avoid anonymous functions in renderItem when possible
  • Set getItemLayout if all items have the same height

Next: handle user input with TextInput and gestures.