Списки: FlatList вместо map

Разбираем, почему длинные списки в RN рисуют через FlatList, а не привычным map, и как с ним работать.

FlatList — компонент для эффективного отображения списков: он рисует только видимые элементы, экономя память на длинных данных.

Почему не map

В React вы привыкли рисовать списки через массив.map(...). В RN так тоже можно — но только для коротких списков. Если элементов сотни, map создаст их все сразу, и приложение начнёт тормозить и есть память.

FlatList решает это: он рендерит только то, что видно на экране, а остальное — по мере прокрутки. Это называется виртуализация. На мобильном с ограниченной памятью это критично.

Базовый FlatList

import { FlatList, Text } from "react-native";

const data = [
  { id: "1", name: "Молоко" },
  { id: "2", name: "Хлеб" },
  { id: "3", name: "Яйца" },
];

function ShoppingList() {
  return (
    <FlatList
      data={data}
      keyExtractor={(item) => item.id}
      renderItem={({ item }) => <Text>{item.name}</Text>}
    />
  );
}

Три обязательных пропа

ПропНазначение
dataмассив данных для списка
renderItemкак нарисовать один элемент
keyExtractorуникальный ключ каждого элемента

renderItem получает объект, из которого мы достаём item — это один элемент массива. keyExtractor возвращает уникальную строку-ключ (как key в React), чтобы RN отслеживал элементы.

Карточка вместо строки

Внутри renderItem можно вернуть любой компонент — например, оформленную карточку:

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

function UserList({ users }) {
  return (
    <FlatList
      data={users}
      keyExtractor={(item) => item.id}
      renderItem={({ item }) => (
        <View style={styles.card}>
          <Text style={styles.name}>{item.name}</Text>
          <Text>{item.email}</Text>
        </View>
      )}
    />
  );
}

const styles = StyleSheet.create({
  card: { padding: 12, borderBottomWidth: 1, borderColor: "#eee" },
  name: { fontWeight: "bold" },
});

Дополнительные возможности

  • ItemSeparatorComponent — разделитель между элементами.
  • ListEmptyComponent — что показать, когда список пуст.
  • onRefresh + refreshing — «потянуть для обновления».
  • onEndReached — подгрузка при прокрутке до конца.

Готовим данные — обычный JS

Часто данные нужно подготовить перед списком. Запускаемый пример — добавим строковый id каждому элементу:

const raw = ["Молоко", "Хлеб", "Яйца"];

const data = raw.map((name, index) => ({
  id: String(index),
  name: name,
}));

console.log(data);

Вывод:

[
  { id: '0', name: 'Молоко' },
  { id: '1', name: 'Хлеб' },
  { id: '2', name: 'Яйца' }
]

Итог

  • FlatList рисует только видимое — экономит память на длинных списках, в отличие от map.
  • Три ключевых пропа: data, renderItem, keyExtractor.
  • Для коротких списков map допустим, но привыкайте к FlatList как к стандарту.
Проверьте себя
1. Почему для длинных списков предпочитают FlatList, а не map?
Amap не работает в React Native
BFlatList рисует только видимые элементы (виртуализация), экономя память
Cmap нельзя использовать с массивами
DFlatList автоматически загружает данные с сервера
2. Что делает проп keyExtractor?
AСортирует элементы списка
BВозвращает уникальный ключ для каждого элемента
CФильтрует данные
DЗадаёт высоту элемента
3. Как получить текущий элемент внутри renderItem?
AЧерез глобальную переменную
BДеструктуризацией: renderItem={({ item }) => ...}
Citem доступен только в keyExtractor
DЧерез this.item
Поддержать проект