Компонент ScrollView у React Native — це контейнер із можливістю прокрутки вмісту, який перевищує розміри екрана. На відміну від FlatList, ScrollView рендерить увесь вміст одразу, що оптимально для невеликих обсягів даних, форм та екранів із відомою висотою. Згідно з React Native Docs, 2024, ScrollView підтримує вертикальну та горизонтальну прокрутку, подію onScroll, програмне керування позицією, а також жести масштабування. Компонент рендериться в нативний UIScrollView на iOS та ScrollView на Android.
Головне
ScrollView — це компонент React Native, який обгортає свій вміст у контейнер із прокруткою. Якщо вміст виходить за межі екрана, користувач може прокручувати його вертикально або горизонтально. ScrollView рендерить усі дочірні елементи під час монтування, незалежно від того, чи видимі вони на екрані.
На відміну від FlatList, який рендерить лише видимі елементи (ліниве рендерування), ScrollView створює всі нативні представлення одразу. Це робить ScrollView зручним для форм, сторінок налаштувань, карток товарів на одному екрані — скрізь, де кількість дочірніх елементів невелика (до 20-30) або їх точна кількість заздалегідь невідома.
Згідно з React Native Using ScrollView, 2024, ScrollView підтримує вкладену прокрутку (наприклад, ScrollView всередині ScrollView), bounce-ефект при досягненні краю, індикатори прокрутки, закріплення позиції (snap) та обробку жестів. На iOS ScrollView автоматично додає відступ під SafeArea через contentInsetAdjustmentBehavior.
ScrollView надає багатий набір властивостей для керування поведінкою прокрутки, зовнішнім виглядом та інтерактивністю. Розглянемо ключові групи: керування скролом, візуальні налаштування, події та платформенні особливості.
horizontal — перемикає напрямок прокрутки з вертикального (за замовчуванням) на горизонтальний. scrollEnabled — вимикає прокрутку за потреби. showsVerticalScrollIndicator та showsHorizontalScrollIndicator керують відображенням індикаторів скролу. bounces (iOS) вмикає/вимикає bounce-ефект при досягненні краю вмісту.
Основна подія — onScroll, яка викликається при кожному скролі та передає об'єкт із nativeEvent, що містить contentOffset (поточна позиція), contentSize (розмір вмісту), layoutMeasurement (розмір видимої області). onMomentumScrollEnd викликається після завершення інерційного скролу. onScrollEndDrag — коли користувач відпустив екран. Ці події використовуються для реалізації нескінченної прокрутки, паралаксу та лінивого завантаження.
ScrollView надає методи для програмного керування через реф: scrollTo({x, y, animated}) прокручує до вказаних координат, scrollToEnd({animated}) — у кінець вмісту, flashScrollIndicators() — тимчасово показує індикатори скролу.
const scrollRef = useRef(null);
// Прокрутити вгору
scrollRef.current.scrollTo({ x: 0, y: 0, animated: true });
// Прокрутити в кінець
scrollRef.current.scrollToEnd({ animated: true });
Програмне керування скролом часто використовується в чатах (автоскрол до останнього повідомлення), формах (скрол до поля з помилкою) та каруселях (програмне перегортання).
Вибір між ScrollView та FlatList — одне з ключових архітектурних рішень у React Native. Обидва компоненти забезпечують прокрутку, але використовують принципово різні стратегії рендерування. ScrollView рендерить усе одразу, FlatList — лише видимі елементи.
| Характеристика | ScrollView | FlatList |
|---|---|---|
| Рендеринг | Всі елементи одразу | Лише видимі + buffer |
| Продуктивність | Падає при 30+ елементах | Стабільна за будь-якої кількості |
| Вміст | Будь-які компоненти (форми, картки) | Однотипні елементи з масиву |
| Розмір даних | Малий та середній (до 30 елементів) | Великий та необмежений |
| Горизонтальний скрол | Так (пропс horizontal) | Так (horizontal) |
| Секції | Ні (рендерить як є) | SectionList для секцій |
Правило вибору: ScrollView — для екранів, де кількість дочірніх елементів відома та не перевищує 20-30 (профіль користувача, форма налаштування, сторінка товару). FlatList — для списків із потенційно великою кількістю елементів (стрічка новин, каталог товарів, повідомлення чату). Якщо вміст різнорідний (заголовок, форма, картка, футер) — ScrollView кращий, оскільки FlatList очікує однотипні елементи.
ScrollView підтримує горизонтальну прокрутку через пропс horizontal, що робить його ідеальним для каруселей, галерей зображень, вкладок та горизонтальних списків. У поєднанні з пропсом pagingEnabled (iOS) або snapToInterval ScrollView перетворюється на компонент для посторінкової навігації.
Властивість horizontal перемикає напрямок прокрутки. pagingEnabled (iOS) вмикає посторінкову прокрутку, при якій скрол зупиняється лише на межах елементів. snapToInterval задає крок прив'язки в пікселях для обох платформ.
const ImageCarousel = ({ images }) => (
<ScrollView
horizontal
pagingEnabled
showsHorizontalScrollIndicator={false}
onMomentumScrollEnd={handlePageChange}
>
{images.map((img, index) => (
<Image
key={index}
source={{ uri: img }}
style={{ width: SCREEN_WIDTH, height: 250 }}
/>
))}
</ScrollView>
);
У цій каруселі pagingEnabled автоматично прив'язує скрол до меж кожного зображення. onMomentumScrollEnd дозволяє оновлювати індикатор поточної сторінки. Така карусель працює нативно та підтримує інерційний скрол.
Для нестандартних кроків прив'язки використовується snapToInterval (розмір кроку в пікселях) та snapToAlignment (start, center, end). За допомогою snapToOffsets можна задати масив конкретних позицій для прив'язки. Це корисно для горизонтальних списків із картками різного розміру.
Розглянемо два типові сценарії: екран із формою (вертикальний скрол) та горизонтальний список категорій. Обидва використовують ScrollView з різними пропсами для оптимальної поведінки.
Сторінка редагування профілю містить різнорідні елементи: аватар, кілька полів введення, перемикачі та кнопку збереження. ScrollView дозволяє скролити всю сторінку цілком, а не кожен блок окремо.
const ProfileScreen = () => (
<ScrollView
contentContainerStyle={styles.container}
keyboardShouldPersistTaps="handled"
showsVerticalScrollIndicator={false}
>
<AvatarPicker />
<TextInput placeholder="Name" />
<TextInput placeholder="Email" />
<TextInput placeholder="About me" multiline />
<SwitchRow label="Notifications" />
<Button title="Save" />
</ScrollView>
);
Пропс keyboardShouldPersistTaps: 'handled' дозволяє скролити та взаємодіяти з формою, коли клавіатура відкрита. contentContainerStyle застосовує відступи до всього вмісту. Цей патерн використовується у всіх екранах із формами в React Native.
Для навігації по категоріях (чати, фільтри, вкладки) використовується горизонтальний ScrollView із чіпсами. Такий компонент часто зустрічається в додатках маркетплейсів та соцмереж.
const CategoryChips = ({ categories, selected, onSelect }) => (
<ScrollView
horizontal
showsHorizontalScrollIndicator={false}
contentContainerStyle={styles.chipContainer}
>
{categories.map((cat) => (
<Chip
key={cat.id}
label={cat.name}
isSelected={selected === cat.id}
onPress={() => onSelect(cat.id)}
/>
))}
</ScrollView>
);
Горизонтальний ScrollView із вимкненим індикатором — стандарт для стрічки категорій. Кожен чіп — окремий компонент зі станом вибору. Пропс showsHorizontalScrollIndicator: false прибирає смугу прокрутки, що відповідає очікуванням користувачів мобільних додатків.
Поширені запитання
ScrollView підходить для невеликих обсягів даних (до 20-30 елементів) та різнорідного вмісту (форми, профілі, екрани налаштувань). FlatList обирайте для довгих однотипних списків — стрічка новин, каталог товарів, повідомлення.
Використовуйте подію onScroll з onScrollEndDrag або onMomentumScrollEnd. У nativeEvent.contentOffset.y міститься поточна вертикальна позиція. Для продуктивності використовуйте ScrollEventThrottle (iOS) для налаштування частоти виклику onScroll.
ScrollView рендерить всі елементи при монтуванні, створюючи нативні представлення для кожного. При 50+ елементах на екрані навантаження на пам'ять та JS-потік зростає, викликаючи падіння кадрів. Для таких випадків використовуйте FlatList із лінивим рендерингом.
Встановіть bounces={false}. Цей пропс працює лише на iOS та вимикає пружинистий ефект при досягненні краю ScrollView. На Android bounce-ефекту немає за замовчуванням, тому пропс ігнорується.
ScrollView не підтримує нескінченну прокрутку нативно. Однак можна комбінувати onScroll із перевіркою наближення до нижнього краю (contentOffset.y + висота екрана >= contentSize.height) та додавати елементи в стан. Для серйозних обсягів використовуйте FlatList із onEndReached.
Підсумки
Ми розробимо мобільний застосунок під ключ
IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.
Читайте також