Проверяет понимание виртуализации списков и ленивой подгрузки данных для эффективного рендеринга больших коллекций без перегрузки памяти и DOM.
Когда в списке тысячи или миллионы элементов, рендерить их все сразу нельзя: браузер создаст огромный DOM, что приведёт к высокому потреблению памяти, долгим layout и лагам. Решение — рендерить только то, что видно пользователю, а остальное подгружать по мере прокрутки. Этот подход называется виртуализацией (windowing) и часто сочетается с бесконечной прокруткой (infinite scroll).
Контейнер списка имеет фиксированную высоту и overflow: auto. Внутри создаётся «фантомный» блок высотой = количество элементов × высота строки, чтобы скроллбар отражал реальный размер. Поверх него рендерятся только видимые строки, позиционированные через transform: translateY. При скролле вычисляется диапазон видимых индексов и обновляется набор отрисованных элементов.
function VirtualList({ items, rowHeight, height }) {
const [scrollTop, setScrollTop] = useState(0);
const start = Math.floor(scrollTop / rowHeight);
const visibleCount = Math.ceil(height / rowHeight);
const end = Math.min(start + visibleCount + 2, items.length);
const visible = items.slice(start, end);
return (
<div style={{ height, overflowY: 'auto' }}
onScroll={e => setScrollTop(e.currentTarget.scrollTop)}>
<div style={{ height: items.length * rowHeight, position: 'relative' }}>
{visible.map((item, i) => (
<div key={item.id}
style={{ position: 'absolute', top: (start + i) * rowHeight, height: rowHeight }}>
{item.title}
</div>
))}
</div>
</div>
);
}Данные тоже не стоит держать все в памяти. Загружаем порциями (пагинация или cursor-based). Когда пользователь приближается к концу загруженного диапазона, запрашиваем следующую страницу. Для отслеживания используют IntersectionObserver на «sentinel»-элементе в конце списка или проверку scrollTop + clientHeight >= scrollHeight - threshold.
const sentinelRef = useRef(null);
useEffect(() => {
const obs = new IntersectionObserver(([entry]) => {
if (entry.isIntersecting && !loading) loadNextPage();
});
if (sentinelRef.current) obs.observe(sentinelRef.current);
return () => obs.disconnect();
}, [loading]);Готовые библиотеки: react-window, react-virtualized, @tanstack/react-virtual, vue-virtual-scroller. Они решают большинство крайних случаев (динамическая высота, горизонтальный скролл, grid).
Итог: виртуализация плюс порционная подгрузка позволяют отображать миллионы сущностей с постоянным потреблением памяти и стабильным FPS. Применяйте этот подход для лент, таблиц, чатов и любых длинных списков, где важны производительность и отзывчивость интерфейса.
Уровень
Рейтинг:
5
Сложность:
6
Навыки
JavaScript
React
Ключевые слова
Подпишись на React Developer в телеграм
Frontend developer
Ментор по Frontend
Полное сопровождение до оффера — без дорогих курсов, с оплатой после трудоустройства
Записаться на консультацию