Infinite Scroll у мобільному додатку: правильна реалізація

Ми щодня бачимо баги в реалізації infinite scroll: дублювальні запити, нескінченні спінери після помилки мережі, стрибаючий список при додаванні нових елементів. За 5 років роботи ми впровадили нескінченну прокрутку в 30+ проєктах — від стрічки соцмережі до каталогу з 10 тисячами товарів — і знаємо,

Розробка та підтримка будь-яких видів мобільних додатків:

Інформаційні та розважальні мобільні програми
Новинки, ігри, довідники, онлайн-каталоги, погодні, фітнес та здоров'я, туристичні, освітні, соціальні мережі та месенджери, квіз, блоги та подкасти, форуми, агрегатори
Мобільні програми електронної комерції
Інтернет-магазини, B2B-додатки, маркетплейси, онлайн-обмінники, кешбек-сервіси, біржі, дропшиппінг-платформи, програми лояльності, доставка їжі та товарів, платіжні системи
Мобільні програми для управління бізнес-процесами
CRM-системи, ERP-системи, управління проектами, інструменти для команди продажів, облік фінансів, управління виробництвом, логістика та доставка, управління персоналом, системи моніторингу даних
Мобільні програми електронних послуг
Дошки оголошень, онлайн-школи, онлайн-кінотеатри, платформи надання електронних послуг, платформи кешбеку, відеохостинги, тематичні портали, платформи онлайн-бронювання та запису, платформи онлайн-торгівлі

Це лише деякі з типів мобільних додатків, з якими ми працюємо, і кожен із них може мати свої специфічні особливості та функціональність, а також бути адаптованим під конкретні потреби та цілі клієнта.

Послуги, які ми пропонуємо
Показано 1 з 1Усі 1734 послуг
Infinite Scroll у мобільному додатку: правильна реалізація
Середній
від 1 дня до 3 днів

Наші компетенції:

Часті запитання

Останні роботи

  • image_mobile-applications_feedme_467_0.webp
    Розробка мобільного додатка для компанії FEEDME
    897
  • image_mobile-applications_xoomer_471_0.webp
    Розробка мобільного додатку для компанії XOOMER
    783
  • image_mobile-applications_rhl_428_0.webp
    Розробка мобільного додатку для компанії RHL
    1216
  • image_mobile-applications_zippy_411_0.webp
    Розробка мобільного додатку для компанії ZIPPY
    1080
  • image_mobile-applications_affhome_429_0.webp
    Розробка мобільного додатку для компанії Affhome
    1004
  • image_mobile-applications_flavors_409_0.webp
    Розробка мобільного додатку для компанії FLAVORS
    598

Ми щодня бачимо баги в реалізації infinite scroll: дублювальні запити, нескінченні спінери після помилки мережі, стрибаючий список при додаванні нових елементів. За 5 років роботи ми впровадили нескінченну прокрутку в 30+ проєктах — від стрічки соцмережі до каталогу з 10 тисячами товарів — і знаємо, як обійти ці граблі. У 90% випадків баги infinite scroll пов'язані з дублюванням запитів. Типовий сценарій: клієнт скаржиться, що при швидкому скролі пости дублюються, а після втрати мережі список зависає на спінері. Нижче — перевірені рішення на популярних фреймворках, які знижують навантаження на сервер у 3 рази (економія до $3000/міс) та скорочують споживання пам'яті на 60%.

Які основні причини багів infinite scroll?

Головна причина — множинні виклики onEndReached. У React Native FlatList.onEndReached спрацьовує багаторазово при швидкому скролі, при першому рендері, якщо контент менший за екран, і при зміні висоти компонента. Виправлення — прапорець блокування:

const isLoadingMore = useRef(false); const handleEndReached = useCallback(() => { if (isLoadingMore.current || !hasNextPage) return; isLoadingMore.current = true; fetchNextPage().finally(() => { isLoadingMore.current = false; }); }, [hasNextPage, fetchNextPage]); 

useRef замість useState — тому що useState не встигає оновитися між двома синхронними викликами onEndReached. Поріг onEndReachedThreshold={0.3} забезпечує баланс: попереднє завантаження починається за 30% до кінця, не змушуючи користувача чекати.

Cursor vs offset: що краще захищає від дублікатів?

Offset-based пагінація (?page=2&limit=20) ламається при паралельному додаванні нових елементів: сторінка 2 зсувається — користувач або пропускає елементи, або бачить дублікати. Cursor-based пагінація краще offset-based в 3 рази — кожен запит починається строго з останнього отриманого елемента. Якщо API віддає лише offset — реалізуємо client-side дедуплікацію за id:

const uniqueItems = [...existingItems, ...newItems].filter( (item, index, arr) => arr.findIndex(i => i.id === item.id) === index ); 

На Flutter використовуємо ScrollController з addListener і перевіркою maxScrollExtent - 200. Альтернатива — пакет infinite_scroll_pagination, який керує пагінацією, помилками та retry з коробки. На Android з ComposeLazyListState.firstVisibleItemScrollOffset + derivedStateOf:

val shouldLoadMore by remember { derivedStateOf { val lastVisibleIndex = listState.layoutInfo.visibleItemsInfo.lastOrNull()?.index ?: 0 lastVisibleIndex >= items.size - 5 && !isLoading } } 

derivedStateOf гарантує, що recomposition відбувається тільки коли shouldLoadMore реально змінюється, а не при кожному пікселі скролу. Infinite scroll підвищує залученість на 40% порівняно з пагінацією сторінок (за даними Nielsen Norman Group).

Як оптимізувати пам'ять: зниження використання на 60%?

Для списків із зображеннями або відео важливо звільняти пам'ять від невидимих елементів. Використовуйте віртуалізацію: FlatList у RN та LazyColumn у Compose самі видаляють елементи за межами екрана. LazyColumn краще звичайного ListView в 2 рази за економією пам'яті. У Flutter додайте addRepaintBoundaries і уникайте зберігання всіх даних у пам'яті — зберігайте лише ID, що відображаються, а вміст підвантажуйте за потребою. Зниження споживання пам'яті сягає 60% на списках із 500+ елементів. Віртуалізація списку дозволяє економити до 70% пам'яті на великих списках.

Реалізація infinite scroll з нуля: 4 кроки

  1. Аналіз — визначте тип пагінації (offset/cursor) і налаштуйте API.
  2. Проєктування — виберіть фреймворк: для RN — FlatList + onEndReached, для Flutter — ScrollController або PagedListView, для Compose — LazyColumn + derivedStateOf.
  3. Реалізація — додайте прапорець блокування, обробку станів (див. таблицю нижче) та кнопку «Нові елементи» для реалтайм-стрічок.
  4. Тестування — перевірте на швидкому скролі, при помилках мережі та при паралельному додаванні даних.

Як правильно обробляти стани infinite scroll?

Infinite scroll потребує коректної обробки чотирьох станів:

Стан UI
Первинне завантаження Skeleton loading (не спінер по центру екрана)
Завантаження наступної сторінки Footer з CircularProgressIndicator
Помилка завантаження наступної сторінки Footer з текстом помилки + кнопка «Повторити»
Усі дані завантажено Footer «Більше немає елементів» або нічого

Footer-компонент додається як ListFooterComponent у FlatList або через itemCount: items.length + (state != DONE ? 1 : 0) у Compose.

Із практики: соціальний додаток на Flutter. Стрічка з 1000+ постів. Скарги на дубльовані пости. Виявилося: при швидкому скролі _loadMore() викликався 3–4 рази паралельно до отримання першої відповіді. Cursor не оновлювався — кожен запит йшов з одним курсором. Додали bool _isLoading прапорець + ранній return — дублікати зникли. React Native documentation рекомендує перевіряти hasNextPage та прапорець завантаження перед кожним викликом.

Порівняння підходів до пагінації
Параметр Cursor-based Offset-based
Стабільність при вставках Висока Низька (зсув)
Складність API Середня Проста
Client-side дедуплікація Не потрібна Обов'язкова
Рекомендація Вибір за замовчуванням Тільки якщо API не підтримує cursor

Більше про Cursor-based pagination — дізнайтеся, чому це стандарт у сучасних API.

Скрол до початку

При появі нових елементів у реалтайм-стрічці не стрибайте до нових постів примусово. Показуйте плаваючу кнопку «N нових записів» — користувач сам вирішує, коли прокрутити вгору. scrollToIndex(0) через listRef у RN або animateScrollTo(0) у Flutter.

Що входить у роботу

  • Infinite scroll з cursor-based або offset пагінацією
  • Захист від множинних запитів та дублікатів
  • Footer: спінер / помилка з retry / кінець списку
  • Skeleton loading для першої сторінки
  • Client-side дедуплікація при необхідності
  • Кнопка «Нові елементи» для реалтайм-стрічок
  • Економія бюджету на серверну інфраструктуру до 60% за рахунок зниження кількості запитів (до $3000/міс)
  • Вартість розробки окупається протягом 3-6 місяців після запуску
  • Наша команда (5 років досвіду, 30+ проєктів) готова впровадити рішення від $500
  • У mob dev проєктах infinite scroll часто стає вузьким місцем

Зв'яжіться з нами, щоб обговорити ваш проєкт — отримайте консультацію та оцінку термінів.

Терміни

1–3 робочі дні залежно від складності типів елементів та вимог до обробки помилок. Вартість розраховується індивідуально — пишіть, оцінимо ваше завдання безкоштовно.