PassFront
  1. PassFront
  2. База знаний
  3. Хуки

Всегда ли достаточно useCallback и useMemo для перерендеринга?

Хуки

Нет, не всегда. useCallback и useMemo сами по себе не предотвращают ни одного перерендера — они лишь стабилизируют ссылки. Работают только в связке с теми, кто эти ссылки сравнивает.

Когда их недостаточно

Нет React.memo на ребёнке. Стабильный колбэк ничего не даёт, если ребёнок не мемоизирован — он перерендерится вместе с родителем в любом случае:

const handleClick = useCallback(() => {}, []);
return <Child onClick={handleClick} />; // Child без memo — рендерится всегда

Нестабильный проп рядом. Один немемоизированный объект/инлайн-JSX ломает всю цепочку:

<MemoChild onClick={stableCb} style={{ margin: 8 }} /> // style новый каждый рендер

children. JSX-дети — новые объекты каждый рендер; React.memo с children почти всегда бесполезен без отдельной мемоизации.

Перерендер не из-за props. Собственный state ребёнка, useContext, useSelector — memo от них не защищает: контекст будит потребителей напрямую.

Причина выше по дереву. Часто проблема в структуре: часто меняющееся состояние живёт слишком высоко, и мемоизировать приходится всё. Спуск состояния вниз или children-как-проп решают без единого useMemo.

Чем дополнять

  • React.memo на дорогих детях (это он пропускает рендер, хуки лишь его «кормят»).
  • Правильная структура состояния и разделение контекстов.
  • Для тяжёлых обновлений — useTransition/useDeferredValue.
  • Для списков — виртуализация: мемоизация не спасёт от тысячи смонтированных строк.

Коротко для собеседования

useCallback/useMemo лишь стабилизируют ссылки — перерендеры пропускает React.memo, и цепочка ломается от одного нестабильного пропа (включая children). Не помогают против обновлений из state/контекста/стора и не заменяют правильную структуру состояния, transitions и виртуализацию.

Другие вопросы раздела