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

Зачем нужны deps в useCallback?

Хуки

deps в useCallback отвечают на вопрос: когда пересоздать мемоизированную функцию. Без правильных deps либо ломается стабильность (цель хука), либо функция работает с устаревшими данными.

Механика

const handleBuy = useCallback(() => {
  submitOrder(productId, quantity);
}, [productId, quantity]);
  • Пока deps не изменились (Object.is поэлементно) — useCallback возвращает ту же ссылку, что и раньше.
  • Изменились — возвращается новая функция, «замкнувшая» свежие значения.

Зачем нужны — двойная роль

Актуальность замыкания. Функция «фотографирует» переменные в момент создания. Если quantity нет в deps, обработчик навсегда останется с первоначальным значением (stale closure) — классический баг:

const handleBuy = useCallback(() => {
  submitOrder(productId, quantity); // quantity всегда 1
}, [productId]); // ❌ quantity пропущен

Осмысленная стабильность. deps определяют, как долго живёт ссылка: пустой массив — навсегда стабильна; [page] — обновляется при смене страницы. От этого зависит, когда перерендерятся memo-дети и перезапустятся эффекты, где функция в зависимостях.

Практические правила

  • Все реактивные значения из тела функции — в deps (ESLint exhaustive-deps).
  • Сеттеры useState/dispatch стабильны — можно не указывать; функциональные сеттеры (setX((x) => ...)) позволяют убрать state из deps.
  • Значения-объекты в deps сами должны быть стабильны (useMemo), иначе useCallback бесполезен.
  • Пустые deps «ради стабильности» при реальных зависимостях — это баг, а не оптимизация.

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

deps в useCallback управляют пересозданием функции: неизменные deps — старая ссылка (стабильность для memo-детей и эффектов), изменившиеся — новая функция со свежим замыканием. Пропуск зависимостей даёт stale closure; сокращать deps правильно через функциональные сеттеры, а не замалчиванием.

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