Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI21 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Что такое Hook
Hook это специальная функция в React, которая позволяет «подцепиться» (hook into) к различным функциям React. Они были введены в React 16.8 и полностью изменили способ написания React компонентов, сделав функциональные компоненты столь же мощными, как компоненты-классы.
История: Компоненты-классы vs Функциональные компоненты
Компоненты-классы (до Hooks)
class Counter extends React.Component {
constructor(props) {
super(props);
this.state = { count: 0 };
}
componentDidMount() {
// Когда компонент монтируется
document.title = this.state.count;
}
componentDidUpdate() {
// Когда компонент обновляется
document.title = this.state.count;
}
componentWillUnmount() {
// Когда компонент удаляется
document.title = 'Reset';
}
render() {
return (
<div>
<p>Count: {this.state.count}</p>
<button onClick={() => this.setState({ count: this.state.count + 1 })}>
Increment
</button>
</div>
);
}
}
Проблемы:
- Логика разбросана по разным методам (componentDidMount, componentDidUpdate)
- Сложно переиспользовать логику между компонентами
- Много boilerplate кода
- Сложно для новичков
Функциональные компоненты (с Hooks)
function Counter() {
const [count, setCount] = React.useState(0);
React.useEffect(() => {
document.title = count;
return () => {
document.title = 'Reset';
};
}, [count]);
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>
Increment
</button>
</div>
);
}
Преимущества:
- Вся логика в одном месте
- Легко переиспользовать (кастомные хуки)
- Меньше кода
- Понятнее для новичков
Что такое Hook - определение
Hook это функция, которая позволяет:
- "Подцепиться" к функциям React (состояние, побочные эффекты, контекст и т.д.)
- Работать только в функциональных компонентах (или других хуках)
- Переиспользовать логику через кастомные хуки
Встроенные Hooks
Hooks для состояния
// 1. useState - управление состоянием
import { useState } from 'react';
function Form() {
const [name, setName] = useState(''); // Начальное значение ''
const [email, setEmail] = useState('');
const [age, setAge] = useState(null);
return (
<form>
<input
value={name}
onChange={(e) => setName(e.target.value)}
placeholder="Name"
/>
<input
value={email}
onChange={(e) => setEmail(e.target.value)}
placeholder="Email"
/>
</form>
);
}
// 2. useReducer - сложное состояние
import { useReducer } from 'react';
function TodoApp() {
const [todos, dispatch] = useReducer(todosReducer, []);
return (
<button onClick={() => dispatch({ type: 'ADD', payload: 'New todo' })}>
Add
</button>
);
}
function todosReducer(state, action) {
if (action.type === 'ADD') {
return [...state, action.payload];
}
return state;
}
Hooks для побочных эффектов
// 1. useEffect - выполнить код после рендера
import { useEffect } from 'react';
function DataFetcher() {
const [data, setData] = useState(null);
useEffect(() => {
fetch('/api/data')
.then(res => res.json())
.then(data => setData(data));
}, []); // Пустой массив - выполнить один раз
return <div>{data && JSON.stringify(data)}</div>;
}
// 2. useLayoutEffect - выполнить ПЕРЕД рендером браузером
import { useLayoutEffect } from 'react';
function MeasureElement() {
const [height, setHeight] = useState(0);
const ref = useRef(null);
useLayoutEffect(() => {
setHeight(ref.current.clientHeight); // Измерить размер
}, []);
return <div ref={ref}>Height: {height}</div>;
}
Hooks для оптимизации
// 1. useCallback - мемоизация функции
import { useCallback } from 'react';
function Parent() {
const [count, setCount] = useState(0);
const handleClick = useCallback(() => {
console.log(count);
}, [count]); // Пересоздать, если count изменился
return <Child onClick={handleClick} />;
}
// 2. useMemo - мемоизация значения
import { useMemo } from 'react';
function ExpensiveComponent({ data }) {
const sortedData = useMemo(() => {
return data.sort((a, b) => a.name.localeCompare(b.name));
}, [data]); // Пересчитать, если data изменилась
return <ul>{sortedData.map(item => <li key={item.id}>{item.name}</li>)}</ul>;
}
Hooks для доступа
// 1. useRef - доступ к DOM или mutable значению
import { useRef } from 'react';
function TextInput() {
const inputRef = useRef(null);
const focusInput = () => {
inputRef.current.focus();
};
return (
<>
<input ref={inputRef} />
<button onClick={focusInput}>Focus</button>
</>
);
}
// 2. useContext - получить значение контекста
import { useContext, createContext } from 'react';
const ThemeContext = createContext();
function ThemedButton() {
const { theme } = useContext(ThemeContext);
return <button style={{ background: theme === 'dark' ? '#000' : '#fff' }}>Click</button>;
}
Кастомные Hooks - переиспользование логики
Можно создавать собственные хуки для переиспользования логики:
// Кастомный хук для формы
function useForm(initialValues) {
const [values, setValues] = useState(initialValues);
const handleChange = (e) => {
const { name, value } = e.target;
setValues(prev => ({ ...prev, [name]: value }));
};
const reset = () => setValues(initialValues);
return { values, handleChange, reset };
}
// Использование в разных компонентах
function LoginForm() {
const { values, handleChange, reset } = useForm({
email: '',
password: ''
});
return (
<form onSubmit={() => { /* submit */ reset(); }}>
<input name="email" value={values.email} onChange={handleChange} />
<input name="password" value={values.password} onChange={handleChange} />
</form>
);
}
function SignupForm() {
const { values, handleChange, reset } = useForm({
name: '',
email: '',
password: ''
});
return (
<form onSubmit={() => { /* submit */ reset(); }}>
<input name="name" value={values.name} onChange={handleChange} />
<input name="email" value={values.email} onChange={handleChange} />
<input name="password" value={values.password} onChange={handleChange} />
</form>
);
}
Другой пример: Fetch Hook
// Кастомный хук для загрузки данных
function useFetch(url) {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
fetch(url)
.then(res => res.json())
.then(data => {
setData(data);
setLoading(false);
})
.catch(err => {
setError(err);
setLoading(false);
});
}, [url]);
return { data, loading, error };
}
// Использование
function UserProfile({ userId }) {
const { data: user, loading, error } = useFetch(`/api/users/${userId}`);
if (loading) return <p>Loading...</p>;
if (error) return <p>Error: {error.message}</p>;
return <div>{user.name}</div>;
}
Правила использования Hooks
// ❌ НЕПРАВИЛЬНО - вызов в условии
function Component() {
if (condition) {
useState(); // ERROR!
}
}
// ✅ ПРАВИЛЬНО
function Component() {
const [state, setState] = useState();
if (condition) {
// Использовать state здесь
}
}
// ❌ НЕПРАВИЛЬНО - вызов в цикле
for (let i = 0; i < 10; i++) {
useState(); // ERROR!
}
// ✅ ПРАВИЛЬНО
const states = [];
for (let i = 0; i < 10; i++) {
states.push(useState()); // Создать в компоненте один раз
}
// ❌ НЕПРАВИЛЬНО - вызов вне компонента
function outsideComponent() {
useState(); // ERROR!
}
// ✅ ПРАВИЛЬНО - только в компонентах или других хуках
function Component() {
useState(); // OK
}
function useCustom() {
useState(); // OK
}
Зачем нужны Hooks
- Переиспользование логики - через кастомные хуки
- Разделение по логике - не по жизненному циклу
- Простота - меньше кода и boilerplate
- Понятность - логика в одном месте
- Тестируемость - хуки легче тестировать чем классы
Итого
Hook это:
- Функция, которая позволяет использовать React функции в функциональных компонентах
- Способ перейти от классов к функциям
- Механизм для переиспользования логики (кастомные хуки)
- Правильный способ управления состоянием в modern React
- Обязательна база знаний для любого React разработчика