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

Где нельзя использовать hooks?

Хуки

Хуки подчиняются правилам хуков: их нельзя вызывать нигде, кроме верхнего уровня функционального компонента или кастомного хука.

Где нельзя

В условиях, циклах и после раннего return:

if (isVisible) {
  const [x, setX] = useState(0);   // ❌
}
for (const item of items) {
  useEffect(...);                   // ❌
}
if (!data) return null;
const [y, setY] = useState(0);      // ❌ хук после раннего return

Во вложенных функциях и колбэках:

const handleClick = () => {
  const [n, setN] = useState(0);    // ❌ в обработчике
};
items.map(() => useMemo(...));      // ❌ в колбэке map
useEffect(() => {
  const [z] = useState(0);          // ❌ внутри эффекта
});

В классовых компонентах — хуки только для функций (в классах — this.state и методы).

В обычных функциях — не компонентах и не хуках: утилиты, сервисы, тесты без renderHook.

На уровне модуля — вне рендера React хуки не работают.

Почему такие ограничения

React хранит состояние хуков связным списком на fiber-узле и сопоставляет ячейки с вызовами по порядку: первый useState — первая ячейка, второй — вторая. Условный вызов сдвигает порядок между рендерами — состояния «переезжают» в чужие хуки, и всё ломается.

Как жить с ограничениями

  • Условность — внутри хука, а не вокруг него: useEffect(() => { if (enabled) ... }, [enabled]).
  • Логика для элементов списка — отдельный компонент на элемент (свои хуки в каждом).
  • Ранние return — после всех хуков.
  • ESLint-плагин react-hooks ловит нарушения автоматически.
  • React 19: хук use — единственное исключение, его можно вызывать условно.

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

Хуки нельзя вызывать: в условиях/циклах/после раннего return, во вложенных функциях и колбэках, в классах, в обычных функциях и на уровне модуля. Причина — состояние сопоставляется по порядку вызовов на fiber. Условия — внутрь хука, элементы списка — в отдельные компоненты; линтер react-hooks следит.

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