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 блокує повторні виклики.
Нескінченне завантаження налаштовується через 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 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.