FlatList — основной компонент React Native для отображения производительных списков с виртуализацией элементов. В отличие от ScrollView, FlatList рендерит только видимые элементы экрана, экономя память и процессор. Компонент поддерживает горизонтальную и вертикальную прокрутку, pull-to-refresh и бесконечную загрузку. Подробнее об архитектуре списков читайте в документации Meta.
Главное
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 — механизм, при котором компонент рендерит только те элементы, которые попадают в видимую область экрана, плюс небольшой буфер с каждой стороны. Остальные элементы не создаются в DOM, что экономит память и ускоряет рендеринг.
При скролле FlatList переиспользует уже созданные View-ячейки, заменяя в них данные. Это предотвращает создание тысяч View для списка из 10 000 элементов. Размер буфера по умолчанию — 10 элементов сверху и снизу от видимой области, но настраивается через windowSize.
| Параметр | По умолчанию | Описание |
|---|---|---|
| windowSize | 21 | Количество страниц для рендеринга (1 страница = высота экрана) |
| initialNumToRender | 10 | Количество элементов при первом рендере |
| maxToRenderPerBatch | 10 | Максимум элементов, рендерящихся за один батч |
| removeClippedSubviews | false | Удаление View за пределами экрана из иерархии |
Оптимальная настройка этих параметров позволяет балансировать между плавностью скролла и потреблением памяти. Для списков с большими элементами рекомендуется уменьшать windowSize до 5-7.
FlatList API включает набор пропсов для настройки отображения и поведения списка. Два обязательных пропса — data (массив данных) и renderItem (функция рендеринга элемента). keyExtractor повышает производительность, предоставляя уникальный ключ для каждого элемента.
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 — шапку и подвал списка. Это позволяет создавать сложные макеты без дополнительной обёртки.
const styles = StyleSheet.create({
item: {
padding: 16,
backgroundColor: '#fff',
borderBottomWidth: 1,
borderBottomColor: '#e0e0e0',
},
separator: {
height: 1,
backgroundColor: '#ccc',
},
});Оптимизация FlatList критически важна для приложений с сотнями и тысячами элементов. Без правильной настройки список может тормозить при скролле, потреблять избыточную память и вызывать вылеты на слабых устройствах.
Первое правило — использовать keyExtractor с уникальными и стабильными идентификаторами. Индексы в качестве ключей приводят к некорректному переиспользованию ячеек и багам с состоянием. Второе — оборачивать renderItem в useCallback и использовать React.memo для компонента-элемента.
Если все элементы имеют одинаковую высоту, getItemLayout позволяет FlatList вычислять позицию скролла без измерения компонентов. Это даёт значительный прирост производительности, особенно при скролле к определённому индексу.
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 для пошаговой прокрутки, как в нативных каруселях. Компонент автоматически обрабатывает моментум и отпускание пальца, останавливаясь на ближайшем элементе.
<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 в FlatList реализуется через пропсы refreshing и onRefresh, работающие в паре с состоянием загрузки. При потягивании списка вниз вызывается onRefresh, а флаг refreshing блокирует повторные вызовы.
Бесконечная загрузка (infinite scroll) настраивается через onEndReached — колбэк, срабатывающий при приближении к концу списка. onEndReachedThreshold определяет, за сколько элементов до конца срабатывает событие. Для пагинации обычно используют cursor-based подход.
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 рендерит все дочерние элементы сразу, подходит только для небольших списков до 20-30 элементов. FlatList оптимален для 100+ элементов.
Мигание возникает при изменении ссылки на массив data. Используйте extraData, передавая туда зависимость, или оборачивайте renderItem в React.memo. Для полного контроля применяйте useMemo для стабилизации ссылок на данные.
FlatList не предназначен для вложения в ScrollView из-за конфликта жестов. Решения: используйте FlatList с nestedScrollEnabled (Android), SectionList для секций, или выносите внешнюю прокрутку в FlatList через ListHeaderComponent.
Используйте Animated API внутри renderItem с задержкой на основе индекса. При скролле применяйте onViewableItemsChanged для триггера анимации. Библиотеки react-native-reanimated и react-native-lottie упрощают создание сложных анимаций появления.
VirtualizedList — базовый компонент виртуализации, на котором построены FlatList и SectionList. FlatList — обёртка VirtualizedList с упрощённым API для плоских списков. VirtualizedList предоставляет более низкоуровневый контроль, но редко используется напрямую.
Итоги
Мы разработаем мобильное приложение под ключ
IT Sectr создаёт приложения для iOS и Android для стартапов и бизнеса с 2017 года. Мы проконсультируем вас и предложим наилучшее решение.
Читайте также