Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Из каких функций можно вызывать хуки
Это один из ключевых правил React, которое необходимо соблюдать для корректной работы приложения. Хуки имеют строгие ограничения на место их вызова.
Правило вызова хуков
Хуки можно вызывать только из:
- React компонентов (функциональные компоненты)
- Кастомных хуков
1. Вызов хуков в React компонентах
Это самый простой и распространенный случай:
function MyComponent() {
const [count, setCount] = React.useState(0);
const [name, setName] = React.useState('');
return (
<div>
<p>Счетчик: {count}</p>
<button onClick={() => setCount(count + 1)}>Увеличить</button>
</div>
);
}
Здесь useState вызывается напрямую в теле функционального компонента.
2. Вызов хуков в кастомных хуках
Кастомные хуки — это функции, которые сами используют другие хуки. Они позволяют переиспользовать логику между компонентами:
// Кастомный хук - правильно
function useFormField(initialValue) {
const [value, setValue] = React.useState(initialValue);
const [error, setError] = React.useState('');
const validate = (val) => {
if (!val) {
setError('Это поле обязательно');
return false;
}
setError('');
return true;
};
return { value, setValue, error, validate };
}
// Использование в компоненте
function LoginForm() {
const email = useFormField('');
const password = useFormField('');
return (
<form>
<input
value={email.value}
onChange={e => email.setValue(e.target.value)}
/>
{email.error && <span>{email.error}</span>}
</form>
);
}
ЧТО НЕЛЬЗЯ ДЕЛАТЬ
Ошибка 1: Вызов хуков в обычных функциях
// Плохо - будет ошибка!
function calculateSum(a, b) {
const [result, setResult] = React.useState(a + b);
return result;
}
// Использование
const MyComponent = () => {
const sum = calculateSum(2, 3); // Error: Invalid hook call
return <div>{sum}</div>;
};
Ошибка 2: Условный вызов хуков
// Плохо - нарушает правило порядка хуков
function MyComponent({ isActive }) {
if (isActive) {
const [count, setCount] = React.useState(0); // Error!
}
return <div>Count</div>;
}
Хуки должны вызываться на верхнем уровне компонента, в одинаковом порядке при каждом рендере.
Ошибка 3: Хуки в циклах
// Плохо - хуки не должны быть в циклах
function MyComponent() {
const items = [1, 2, 3];
items.forEach(item => {
const [state, setState] = React.useState(item); // Error!
});
return <div>Items</div>;
}
Ошибка 4: Вызов из обработчиков событий
// Плохо
function MyComponent() {
const handleClick = () => {
const [count, setCount] = React.useState(0); // Error!
};
return <button onClick={handleClick}>Click</button>;
}
Почему так?
Причина 1: Порядок вызовов
React полагается на порядок вызовов хуков для связи состояния с компонентом. Если вы вызываете хуки условно или в циклах, порядок может измениться, и React не сможет корректно управлять состоянием.
// Правильно - один порядок всегда
function MyComponent({ showEmail }) {
const [name, setName] = React.useState('');
const [email, setEmail] = React.useState(''); // Всегда второй
const [phone, setPhone] = React.useState(''); // Всегда третий
if (!showEmail) {
return <div>Имя: {name}</div>; // email и phone хуки уже созданы
}
}
Причина 2: Lifecycle хуков
Хуки работают на основе жизненного цикла компонента. Если вызвать хук из обычной функции, он потеряет связь с компонентом и его жизненным циклом.
Правильные паттерны
Паттерн 1: Извлечение логики в кастомный хук
// Вместо вызова хука в обычной функции
function useCounter() {
const [count, setCount] = React.useState(0);
const increment = () => setCount(c => c + 1);
const decrement = () => setCount(c => c - 1);
return { count, increment, decrement };
}
function MyComponent() {
const { count, increment, decrement } = useCounter();
return (
<div>
<p>Count: {count}</p>
<button onClick={increment}>+</button>
<button onClick={decrement}>-</button>
</div>
);
}
Паттерн 2: Использование useCallback для обработчиков
function MyComponent() {
const [count, setCount] = React.useState(0);
// useCallback - это хук, поэтому вызываем его в компоненте
const handleIncrement = React.useCallback(() => {
setCount(c => c + 1);
}, []);
return <button onClick={handleIncrement}>+</button>;
}
Инструменты для проверки
В режиме разработки React покажет ошибку в консоли с подробным объяснением:
Error: Invalid hook call. Hooks can only be called inside the body of a function component...
Также можно использовать ESLint плагин eslint-plugin-react-hooks, который предупредит о нарушении правил на этапе разработки.
Итоги
- Хуки вызываются ТОЛЬКО в React компонентах и кастомных хуках
- Порядок вызовов должен быть одинаковым при каждом рендере
- Нельзя вызывать хуки условно, в циклах или в обычных функциях
- Это правило обеспечивает корректное управление состоянием и жизненным циклом компонентов