Сравни варианты оптимизации компонентов и объясни, когда выбирать каждый вариант.
Рендеринг и производительность
Оптимизация компонента — выбор из нескольких инструментов; правильный зависит от того, что именно дорого: сам рендер, его частота, объём DOM или блокировка ввода.
React.memo — пропустить рендер
Когда: компонент часто получает те же props при рендере родителя, а его рендер заметен (строки таблиц, карточки, тяжёлые виджеты). Цена: сравнение props каждый рендер; ломается одним нестабильным пропом (включая children).
useMemo / useCallback — стабильность и кеш
Когда: дорогое вычисление в рендере (сортировка тысяч элементов) или нужна стабильная ссылка для memo-ребёнка / deps эффекта. Не выбирать: для дешёвых вычислений — сравнение deps не бесплатно.
Структурные приёмы — часто лучше мемоизации
- Спуск состояния вниз: частый state (ввод, hover) — в маленький компонент.
- children как проп: обёртка со state не рендерит переданных детей.
- Разделение контекстов + мемоизация value.
- Узкие селекторы стора.
Когда: перерендеры идут «сверху» — правится причина, а не симптом; кода меньше, хрупкости меньше.
Виртуализация (react-window/virtuoso)
Когда: сотни-тысячи элементов в DOM. Никакая мемоизация не спасёт от количества смонтированных узлов.
useTransition / useDeferredValue
Когда: тяжёлое обновление блокирует ввод (фильтрация по мере набора). Не уменьшает работу, но делает интерфейс отзывчивым.
React.lazy + Suspense
Когда: проблема не в рендере, а в размере бандла/времени загрузки (редактор, графики, модалки).
Порядок действий
Профайлер (production-сборка) → понять причину (частота? стоимость? количество? бандл?) → структурные правки → точечная мемоизация → перепроверить. React Compiler (React 19) снимает необходимость ручных useMemo/useCallback.
Коротко для собеседования
Много рендеров с теми же props → React.memo (+ useCallback/useMemo для стабильных props). Дорогое вычисление → useMemo. Причина в структуре → спуск состояния, children-как-проп, раздельные контексты, узкие селекторы. Тысячи элементов → виртуализация. Блокировка ввода → useTransition. Большой бандл → React.lazy. Всегда после профилирования.