Головна/React і Next.js/Блупринти/Стейт & Real-time/Виртуализированный каталог на 100 000+ позиций с TanStack Virtual и скроллом
До карток розділу «Стейт & Real-time»
Стейт & Real-time(ТЗ 6 из 10)
ТЗ: Виртуализированный каталог на 100 000+ позиций с TanStack Virtual и скроллом
Стейт & Real-time1 шагов • +5 XP

ТЗ: Виртуализированный каталог на 100 000+ позиций с TanStack Virtual и скроллом

Инженерный блупринт для сверхтяжелых датасетов: динамическая виртуализация окон с TanStack Virtual, бесконечная прокрутка TanStack Query, удержание позиции скролла и отладка INP.

~12 ч работыTanStack Virtual v3TanStack Query v5Dynamic Row HeightsScroll RestorationReact 19 useTransition
+5 XP за шаг
Выполнено 0 из 1 шагов (0%)
Трудозатраты~12 рабочих часов
Фриланс вилка~$540 – $900 (€480 – €840)
Оценка веб-студии~$1,140 – $1,920 (€1080 – €1800)

ТЗ заказчика (исходный бриф):

Никаких зависаний при прокрутке. Таблица должна рендерить в DOM только видимые строки (15-20 штук) и мгновенно скроллиться на 100 000-ю строку без создания сотен тысяч DOM-узлов.
Ключевые требования:
  • •Использование TanStack Virtual для виртуализации окон (windowing)
  • •Поддержка динамической высоты строк через measureElement
  • •Бесконечная подгрузка страниц чанками по 100 записей через fetchNextPage
  • •Сохранение позиции скролла при переходе в карточку товара и возврате обратно
Ограничения проекта:
  • •Количество DOM-узлов таблицы не должно превышать 50 независимо от размера каталога
  • •Запрет на блокировку главного потока при быстром fling-скролле
Критерии приёмки (KPI):
  • Потребление памяти браузером < 80 МБ при 100k записях
  • Interaction to Next Paint (INP) < 40ms при фильтрации

Пошаговое практическое руководство по ТЗ

Подробный разбор архитектуры, код реализации и советы эксперта по каждому этапу:

1
Этап 1 из 1

Настройка виртуального контейнера с динамическим замером высоты

~60 минСложный

Практическое руководство:

Реализовать компонент VirtualTable с хуком useVirtualizer, контейнером скролла и абсолютным позиционированием видимых строк через CSS transform.

Важные технические нюансы и подводные камни:

Всегда используйте transform: translateY(...) вместо top для плавной отрисовки на GPU.

Архитектурная база (Почему выбрано такое решение):

translateY запускает аппаратное ускорение композитинга GPU и не вызывает перерасчета геометрии Layout всего документа.

Совет эксперта (Best Practice):

Опция overscan: 5 рендерит по 5 строк выше и ниже экрана, исключая появление пустых белых полос при резком скролле.

Ожидаемый артефакт этапа:

Компонент VirtualTable с плавной прокруткой и GPU-ускорением.

TYPESCRIPT
'use client'

import React, { useRef } from 'react'
import { useVirtualizer } from '@tanstack/react-virtual'

interface VirtualTableProps<T> {
  items: T[]
  renderRow: (item: T, index: number) => React.ReactNode
  estimateSize?: number
}

export function VirtualTable<T>({ items, renderRow, estimateSize = 56 }: VirtualTableProps<T>) {
  const parentRef = useRef<HTMLDivElement>(null)

  const rowVirtualizer = useVirtualizer({
    count: items.length,
    getScrollElement: () => parentRef.current,
    estimateSize: () => estimateSize,
    overscan: 5
  })

  return (
    <div
      ref={parentRef}
      className="h-[600px] overflow-auto border border-border rounded-xl bg-bg-surface custom-scrollbar relative"
    >
      <div
        style={{
          height: `${rowVirtualizer.getTotalSize()}px`,
          width: '100%',
          position: 'relative'
        }}
      >
        {rowVirtualizer.getVirtualItems().map((virtualRow) => {
          const item = items[virtualRow.index]
          return (
            <div
              key={virtualRow.key}
              ref={rowVirtualizer.measureElement}
              data-index={virtualRow.index}
              style={{
                position: 'absolute',
                top: 0,
                left: 0,
                width: '100%',
                transform: `translateY(${virtualRow.start}px)`
              }}
            >
              {renderRow(item, virtualRow.index)}
            </div>
          )
        })}
      </div>
    </div>
  )
}

Типичные грабли на этом ТЗ

1 антипаттерна

Что сдаём клиенту (Deliverables)

Чек-лист сдачи
Виртуализированный контейнер таблицы TanStack Virtual v3
Бесконечная подгрузка данных частями
Сохранение позиции скролла при навигации