FlatList: что это, API и оптимизация в React Native

Автор: IT Sectr Опубликовано: 2026-07-05 Время чтения: 10 мин

FlatList — основной компонент React Native для отображения производительных списков с виртуализацией элементов. В отличие от ScrollView, FlatList рендерит только видимые элементы экрана, экономя память и процессор. Компонент поддерживает горизонтальную и вертикальную прокрутку, pull-to-refresh и бесконечную загрузку. Подробнее об архитектуре списков читайте в документации Meta.

Главное

  • FlatList — виртуализированный компонент списка, который рендерит только видимые элементы и переиспользует их при скролле
  • Производительность достигается за счёт оконного рендеринга (windowing) — элементы за пределами экрана не создаются
  • API включает renderItem, keyExtractor, ItemSeparatorComponent, ListHeaderComponent и ListFooterComponent
  • Горизонтальные списки настраиваются через флаг horizontal и меняют направление прокрутки на ось X
  • Оптимизация требует правильной настройки keyExtractor, useMemo для данных и getItemLayout для фиксированных размеров

Что такое FlatList?

FlatList — компонент React Native, реализующий виртуализированный список с производительным рендерингом больших объёмов данных. Компонент построен поверх VirtualizedList и предоставляет декларативный API для создания плоских списков любой сложности.

FlatList появился в React Native 0.43 как замена устаревшему ListView. По данным Meta (2026), FlatList используется в 85% приложений на React Native, работающих со списками. Компонент поддерживает все распространённые сценарии: контакты, ленты новостей, каталоги товаров, чаты.

История и место в экосистеме

До появления FlatList разработчики использовали ListView, который требовал ручной настройки переиспользования ячеек. FlatList автоматизировал этот процесс, внедрив оконный рендеринг по аналогии с RecyclerView в Android (2014) и UICollectionView в iOS (2012). В современных проектах FlatList — стандарт де-факто для любых списков.

Как работает виртуализация FlatList

Виртуализация FlatList — механизм, при котором компонент рендерит только те элементы, которые попадают в видимую область экрана, плюс небольшой буфер с каждой стороны. Остальные элементы не создаются в DOM, что экономит память и ускоряет рендеринг.

При скролле FlatList переиспользует уже созданные View-ячейки, заменяя в них данные. Это предотвращает создание тысяч View для списка из 10 000 элементов. Размер буфера по умолчанию — 10 элементов сверху и снизу от видимой области, но настраивается через windowSize.

ПараметрПо умолчаниюОписание
windowSize21Количество страниц для рендеринга (1 страница = высота экрана)
initialNumToRender10Количество элементов при первом рендере
maxToRenderPerBatch10Максимум элементов, рендерящихся за один батч
removeClippedSubviewsfalseУдаление View за пределами экрана из иерархии

Оптимальная настройка этих параметров позволяет балансировать между плавностью скролла и потреблением памяти. Для списков с большими элементами рекомендуется уменьшать windowSize до 5-7.

API и основные пропсы FlatList

FlatList API включает набор пропсов для настройки отображения и поведения списка. Два обязательных пропса — data (массив данных) и renderItem (функция рендеринга элемента). keyExtractor повышает производительность, предоставляя уникальный ключ для каждого элемента.

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

const App = () => {
  const data = Array.from({ length: 100 }, (_, i) => ({
    id: i.toString(),
    title: `Item #${i + 1}`,
  }));

  return (
    <FlatList
      data={data}
      renderItem={({ item }) => (
        <View style={styles.item}>
          <Text>{item.title}</Text>
        </View>
      )}
      keyExtractor={item => item.id}
      ItemSeparatorComponent={() => <View style={styles.separator} />}
    />
  );
};

ItemSeparatorComponent добавляет разделитель между элементами, ListHeaderComponent и ListFooterComponent — шапку и подвал списка. Это позволяет создавать сложные макеты без дополнительной обёртки.

js
const styles = StyleSheet.create({
  item: {
    padding: 16,
    backgroundColor: '#fff',
    borderBottomWidth: 1,
    borderBottomColor: '#e0e0e0',
  },
  separator: {
    height: 1,
    backgroundColor: '#ccc',
  },
});

Оптимизация производительности FlatList

Оптимизация FlatList критически важна для приложений с сотнями и тысячами элементов. Без правильной настройки список может тормозить при скролле, потреблять избыточную память и вызывать вылеты на слабых устройствах.

Первое правило — использовать keyExtractor с уникальными и стабильными идентификаторами. Индексы в качестве ключей приводят к некорректному переиспользованию ячеек и багам с состоянием. Второе — оборачивать renderItem в useCallback и использовать React.memo для компонента-элемента.

getItemLayout для фиксированной высоты

Если все элементы имеют одинаковую высоту, getItemLayout позволяет FlatList вычислять позицию скролла без измерения компонентов. Это даёт значительный прирост производительности, особенно при скролле к определённому индексу.

js
const ITEM_HEIGHT = 80;

const getItemLayout = (data, index) => ({
  length: ITEM_HEIGHT,
  offset: ITEM_HEIGHT * index,
  index,
});

<FlatList
  data={data}
  getItemLayout={getItemLayout}
  renderItem={renderItem}
/FlatList>

useMemo для данных предотвращает лишние перерендеры. Если данные приходят из API, преобразуйте их один раз и кешируйте. Используйте React.memo для компонента элемента, чтобы избежать рендеринга неизменившихся элементов.

Горизонтальные списки и карусели

Горизонтальный FlatList создаётся добавлением пропса horizontal={true}. Список меняет направление прокрутки на ось X, что удобно для каруселей товаров, галерей изображений и горизонтальных меню.

В горизонтальном режиме важно правильно настроить snapToInterval и snapToAlignment для пошаговой прокрутки, как в нативных каруселях. Компонент автоматически обрабатывает моментум и отпускание пальца, останавливаясь на ближайшем элементе.

js
<FlatList
  horizontal
  data={images}
  renderItem={renderItem}
  keyExtractor={item => item.id}
  showsHorizontalScrollIndicator={false}
  snapToInterval={CARD_WIDTH + GAP}
  snapToAlignment="start"
  decelerationRate="fast"
  pagingEnabled
  onViewableItemsChanged={onViewableItemsChanged}
/>

onViewableItemsChanged — колбэк, вызываемый при изменении видимых элементов. Используется для аналитики, ленивой загрузки изображений и активации видео только для видимых карточек.

Pull-to-refresh и бесконечная загрузка

Pull-to-refresh в FlatList реализуется через пропсы refreshing и onRefresh, работающие в паре с состоянием загрузки. При потягивании списка вниз вызывается onRefresh, а флаг refreshing блокирует повторные вызовы.

Бесконечная загрузка (infinite scroll) настраивается через onEndReached — колбэк, срабатывающий при приближении к концу списка. onEndReachedThreshold определяет, за сколько элементов до конца срабатывает событие. Для пагинации обычно используют cursor-based подход.

js
const ListWithPagination = () => {
  const [data, setData] = React.useState([]);
  const [page, setPage] = React.useState(1);
  const [refreshing, setRefreshing] = React.useState(false);

  const loadMore = React.useCallback(async () => {
    const newData = await fetchPage(page);
    setData(prev => [...prev, ...newData]);
    setPage(p => p + 1);
  }, [page]);

  return (
    <FlatList
      data={data}
      renderItem={renderItem}
      keyExtractor={item => item.id}
      refreshing={refreshing}
      onRefresh={loadMore}
      onEndReached={loadMore}
      onEndReachedThreshold={0.5}
    />
  );
};

Важно: onEndReached может вызываться многократно. Добавьте флаг isLoading для блокировки повторных запросов, пока предыдущий не завершился. Используйте ActivityIndicator в ListFooterComponent для индикации загрузки.

Часто задаваемые вопросы

Чем FlatList отличается от ScrollView?

FlatList использует виртуализацию — рендерит только видимые элементы, что экономит память при больших данных. ScrollView рендерит все дочерние элементы сразу, подходит только для небольших списков до 20-30 элементов. FlatList оптимален для 100+ элементов.

Как исправить мигание (flash) при обновлении данных FlatList?

Мигание возникает при изменении ссылки на массив data. Используйте extraData, передавая туда зависимость, или оборачивайте renderItem в React.memo. Для полного контроля применяйте useMemo для стабилизации ссылок на данные.

Почему FlatList не скроллится внутри другого скролл-вью?

FlatList не предназначен для вложения в ScrollView из-за конфликта жестов. Решения: используйте FlatList с nestedScrollEnabled (Android), SectionList для секций, или выносите внешнюю прокрутку в FlatList через ListHeaderComponent.

Как анимировать появление элементов FlatList?

Используйте Animated API внутри renderItem с задержкой на основе индекса. При скролле применяйте onViewableItemsChanged для триггера анимации. Библиотеки react-native-reanimated и react-native-lottie упрощают создание сложных анимаций появления.

Что такое VirtualizedList и как он связан с FlatList?

VirtualizedList — базовый компонент виртуализации, на котором построены FlatList и SectionList. FlatList — обёртка VirtualizedList с упрощённым API для плоских списков. VirtualizedList предоставляет более низкоуровневый контроль, но редко используется напрямую.

Итоги

  • FlatList — основной компонент React Native для производительных списков с автоматической виртуализацией и переиспользованием ячеек
  • Виртуализация рендерит только видимые элементы через windowSize и initialNumToRender, экономя память на больших наборах данных
  • Обязательные пропсы: data, renderItem и keyExtractor — обеспечивают корректную работу списка
  • getItemLayout ускоряет скролл для элементов с фиксированной высотой, избавляя от динамического измерения
  • Горизонтальные списки и карусели настраиваются через horizontal и snapToInterval для пошаговой прокрутки
  • Pull-to-refresh и onEndReached реализуют бесконечную загрузку с защитой от повторных вызовов
  • React.memo и useCallback обязательны для renderItem — без них каждый скролл вызывает перерендер всех элементов

Мы разработаем мобильное приложение под ключ

IT Sectr создаёт приложения для iOS и Android для стартапов и бизнеса с 2017 года. Мы проконсультируем вас и предложим наилучшее решение.

Обсудить проект

Читайте также