В чём разница между ScrollView и FlatList на практике?
ScrollView и FlatList в React Native — это два компонента для отображения прокручиваемого списка контента. На первый взгляд они похожи: оба позволяют скроллировать вертикально или горизонтально, использовать стили, загружать изображения и отображать текст. Однако их поведение, производительность и предназначение существенно различаются.
ScrollView
ScrollView — это компонент, который рендерит всё содержимое сразу, независимо от его объёма. Он предназначен для отображения небольшого количества элементов, которые не требуют динамической подгрузки.
Особенности:
-
Подходит для отображения фиксированных или небольших списков
-
Рендерит все дочерние элементы сразу
-
Позволяет использовать произвольные компоненты внутри (вложенные View, Image, Text и т.д.)
-
Может быть вложенным (nested ScrollView)
-
Полностью контролируется вручную — нет оптимизаций рендера, виртуализации или lazy-loading
Пример:
import { ScrollView, Text } from 'react-native';
function MyScrollView() {
return (
<ScrollView>
<Text>Элемент 1</Text>
<Text>Элемент 2</Text>
{/\* и так далее \*/}
</ScrollView>
);
}
Плюсы:
-
Простота использования
-
Полная свобода в построении макета
-
Хорошо работает с неструктурированными UI
Минусы:
-
Плохая производительность при большом количестве элементов
-
Загружает всю память сразу — даже невидимые элементы находятся в DOM
-
Нет встроенной поддержки оптимизаций (виртуализация, recycling)
FlatList
FlatList — это компонент, созданный специально для работы с большими списками данных, например, массивов из сотен или тысяч элементов. Он реализует виртуализацию: рендерит только те элементы, которые видны на экране + небольшой буфер, и удаляет элементы, выходящие за пределы области видимости.
Особенности:
-
Принимает массив данных через data
-
Каждый элемент отображается через функцию renderItem
-
Требует keyExtractor или key для каждого элемента
-
Автоматически обрабатывает виртуализацию и оптимизацию
-
Позволяет использовать initialNumToRender, onEndReached, ListHeaderComponent, ListFooterComponent, ItemSeparatorComponent
Пример:
import { FlatList, Text } from 'react-native';
const DATA = \[
{ id: '1', title: 'Первый' },
{ id: '2', title: 'Второй' },
// ...
\];
function MyFlatList() {
return (
<FlatList
data={DATA}
keyExtractor={(item) => item.id}
renderItem={({ item }) => <Text>{item.title}</Text>}
/>
);
}
Плюсы:
-
Отличная производительность при больших объёмах данных
-
Рендерит только видимые элементы
-
Поддержка бесконечного скролла через onEndReached
-
Простая интеграция с API (списки из серверных данных)
-
Опциональная поддержка refreshing для pull-to-refresh
Минусы:
-
Требует более строгой структуры
-
Нельзя использовать произвольный JSX между элементами (всё управляется через renderItem)
-
Меньшая гибкость по сравнению с ScrollView, особенно для кастомной вёрстки
Сравнение ScrollView vs FlatList
Свойство | ScrollView | FlatList |
---|---|---|
Рендер всех элементов | Да | Только видимых |
--- | --- | --- |
Производительность | Падает при большом количестве элементов | Высокая даже с тысячами элементов |
--- | --- | --- |
Использование данных | Не требует массива | Обязательно data и renderItem |
--- | --- | --- |
Виртуализация | Нет | Да |
--- | --- | --- |
Поддержка onEndReached | Нет | Да (используется для подгрузки данных) |
--- | --- | --- |
Поддержка pull to refresh | Нет | Да (refreshing, onRefresh) |
--- | --- | --- |
Вложенные списки | Поддерживаются, но ресурсоёмко | Не рекомендуется |
--- | --- | --- |
Легкость реализации | Очень простая | Немного сложнее (но масштабируемая) |
--- | --- | --- |
Кастомизация UI | Максимальная гибкость | Ограничена внутри renderItem |
--- | --- | --- |
Уместен при | Небольшое количество элементов (<30) | Средние и большие списки (10+ до ∞) |
--- | --- | --- |
Как работает виртуализация в FlatList
FlatList строит список виртуально:
- Создаёт и монтирует на экран **только видимые элементы
** -
Удаляет элементы из DOM, как только они покидают видимую область
-
Перерабатывает (recycle) существующие компоненты для повторного использования
-
Позволяет указывать сколько элементов рендерить заранее: initialNumToRender, maxToRenderPerBatch
-
Позволяет управлять расстоянием до конца списка, когда срабатывает onEndReached
Что использовать: ScrollView или FlatList?
Используй ScrollView, если:
-
У тебя несколько (10–15) элементов
-
Контент статичен (не зависит от данных)
-
Не требуется lazy loading или подгрузка
-
Уникальная/сложная вёрстка между элементами
-
Не нужна производительность при прокрутке
Используй FlatList, если:
-
Есть массив данных (даже если из 10 элементов)
-
Планируется подгрузка новых данных (бесконечный скролл)
-
Нужно обновление списка (pull-to-refresh)
-
Ожидается рост количества элементов
-
Требуется производительность и виртуализация
Альтернатива: SectionList
Если нужно отобразить данные с разделами (например, по дате или категории), вместо FlatList можно использовать SectionList. Это расширение FlatList с группировкой.
<SectionList
sections={\[
{ title: 'A', data: \['Apple', 'Avocado'\] },
{ title: 'B', data: \['Banana', 'Blueberry'\] }
\]}
renderItem={({ item }) => <Text>{item}</Text>}
renderSectionHeader={({ section }) => <Text>{section.title}</Text>}
/>
Выбор между ScrollView и FlatList должен опираться на количество отображаемых данных, структуру списка, требования к производительности и масштабируемости. В большинстве современных проектов, особенно с API, почти всегда предпочтение отдаётся FlatList.