Где нельзя использовать 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 следит.