Какие рекомендации по оптимизации компонента с большим списком, включая виртуализацию и разбиение на хуки
Что проверяют
Понимаете ли вы, откуда берутся тормоза в длинном списке: слишком много DOM-узлов или лишние перерисовки. Следом обычно просят объяснить, как виртуализация работает при строках разной высоты и что происходит при вводе в фильтр над списком.
Как отвечать
Сначала измерьте: React DevTools Profiler покажет, что и почему перерисовывается, вкладка Performance покажет, сколько стоит сам DOM. Дальше:
- виртуализация: в DOM держатся только видимые строки плюс небольшой запас (
overscan), остальное заменяют отступы. Инструменты:@tanstack/react-virtualс хукомuseVirtualizerиmeasureElementдля динамической высоты,react-window,react-virtuoso. Цена: не работает поиск браузера по странице, нужна забота о фокусе и доступности; - подгрузка частями: бесконечная прокрутка через
IntersectionObserverна последней строке илиuseInfiniteQueryиз TanStack Query, либо обычная пагинация; - стабильные
key:idэлемента, а не индекс; - мемоизация строки:
React.memoна компоненте строки плюс стабильные пропсы. Обработчики черезuseCallbackили один обработчик на весь список, которому строка передаётid. Если в проекте включён React Compiler, большую часть ручной мемоизации он делает сам; - отзывчивый фильтр:
useDeferredValueилиuseTransition, чтобы ввод не ждал пересчёта тысяч строк; - разбиение на хуки:
useListDataдля загрузки,useFilteredItemsсuseMemoдля фильтрации и сортировки,useSelectionдля выделения. Это делает логику тестируемой, а скорость дают правильное место хранения состояния и мемоизация внутри хуков.
Где спотыкаются
Считают, что вынос логики в хуки сам по себе ускоряет компонент. Кастомный хук это организация кода: если его состояние живёт в корне списка, любое изменение перерисует всё так же.
Оборачивают строку в React.memo, но передают ей новый объект стиля или стрелочную функцию на каждый рендер. Сравнение пропсов проваливается всегда, а его стоимость добавляется.
Используют индекс как key в списке с фильтрацией или вставкой сверху. React переиспользует не те строки, и локальное состояние, например введённый текст, переезжает к чужому элементу.