Какие нюансы в работе React Hooks важны на практике и как их применять?
Хуки
У хуков есть набор практических нюансов, которые не видны в туториалах, но регулярно стреляют в продакшене.
Правила вызова
Хуки — только на верхнем уровне функции компонента (или другого хука): не в условиях, циклах, вложенных функциях. React сопоставляет state с вызовами по порядку; условный вызов сдвигает порядок и перемешивает состояния. Ранний return до хуков — та же ошибка.
Замыкания — главный источник багов
Каждый рендер — свой «снимок» props/state. Колбэк из старого рендера видит старые значения:
useEffect(() => {
const id = setInterval(() => setCount(count + 1), 1000); // навсегда count из первого рендера
return () => clearInterval(id);
}, []);
// решение: setCount((c) => c + 1) или честная зависимость [count]Зависимости
- exhaustive-deps не выключать: пропущенная зависимость — устаревшие данные.
- Нестабильные ссылки (объекты/функции из рендера) в deps — перезапуск каждый рендер; лечится useMemo/useCallback или переносом внутрь.
- Сеттеры useState и dispatch стабильны — в deps не нужны.
Асинхронность
- setState не меняет переменную в текущем замыкании — новое значение придёт со следующим рендером.
- Несколько setState в одном обработчике батчатся (React 18 — везде) — один рендер.
- Эффект не может быть async; отмена через флаг/AbortController в cleanup — защита от гонок.
StrictMode
В dev монтирование двойное (mount → unmount → mount): эффекты обязаны корректно чиститься, инициализация — быть идемпотентной.
Кастомные хуки
Каждый вызов — независимое состояние (шарится логика, не данные); имя обязательно с use — иначе линтер не проверит правила.
Коротко для собеседования
Нюансы: хуки только на верхнем уровне (порядок вызовов), устаревшие замыкания (функциональные сеттеры/честные deps), нестабильные ссылки в зависимостях, батчинг и асинхронность setState, двойное монтирование StrictMode, независимость состояния кастомных хуков. Большинство «мистических багов» с хуками — одно из этого списка.