Какие проблемы возникают при бесконечном scroll на React?
Основы React
Бесконечный скролл кажется простым (подгрузить следующую страницу), но собирает целый букет проблем — от производительности до UX.
Производительность DOM
Элементы накапливаются: после десяти страниц в DOM тысячи узлов — память, тормоза рендера и скролла. Лечение: виртуализация (react-window, react-virtuoso), рендерящая только видимое окно; она же снимает проблему высоты списка.
Дубли и пропуски данных
Пагинация по offset ломается, когда данные меняются между запросами (добавилась запись — элемент дублируется или пропускается). Лечение: курсорная пагинация (cursor/after), а не page=N.
Гонки и дубли запросов
Быстрый скролл триггерит несколько загрузок одной страницы; ответы приходят вразнобой. Лечение: флаг isFetchingNextPage, дедупликация по ключу — useInfiniteQuery из TanStack Query решает это, плюс отмена и ретраи.
Триггер загрузки
onScroll с расчётом offsetHeight — дорого и дёргано. Лечение: IntersectionObserver на элементе-сентинеле внизу списка (с rootMargin для предзагрузки).
Скачки скролла (scroll jank)
Вставка элементов сверху или изменение высоты уже отрисованных (подгрузились картинки) сдвигает контент. Лечение: резервировать размеры (aspect-ratio, скелетоны фиксированной высоты), CSS overflow-anchor.
UX и доступность
- Недостижимый футер; невозможность «вернуться на то же место» после перехода в карточку и назад (нужно сохранение позиции и загруженных страниц — кеш React Query помогает).
- Нет ощущения объёма и конца списка; трудно поделиться «страницей».
- Клавиатурная навигация и скринридеры: нужны aria-live для сообщений о подгрузке, кнопка «Загрузить ещё» как fallback.
- SEO: контент за скроллом не индексируется — для публичных страниц лучше пагинация.
Коротко для собеседования
Проблемы: рост DOM (нужна виртуализация), дубли/пропуски при offset-пагинации (курсоры), гонки и дубли запросов (useInfiniteQuery), дорогой onScroll (IntersectionObserver), скачки скролла (резерв высоты), UX — недостижимый футер, потеря позиции при возврате, доступность и SEO (fallback «Загрузить ещё»/пагинация).