Комментарии (2)
Ответ сгенерирован нейросетью и может содержать ошибки
Основные хуки React (Hooks)
Я работаю с React с момента выхода хуков в 2019 году (React 16.8) и активно применяю их во всех проектах. Хуки — это функции, которые позволяют использовать состояние и другие возможности React без написания классов. Они революционизировали разработку на React, сделав код более компактным, читаемым и reusable.
Все хуки можно разделить на три основные категории: базовые (используются в 95% компонентов), дополнительные (для оптимизации и side effects) и пользовательские (собственная логика).
📌 Базовые хуки (Basic Hooks)
Эти хуки используются практически в каждом функциональном компоненте.
useState
Управляет внутренним состоянием компонента. Возвращает массив из двух элементов: текущее значение состояния и функцию для его обновления.
```javascript
import React, { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0); // Инициализация
return (
<div>
<p>Вы кликнули {count} раз</p>
<button onClick={() => setCount(count + 1)}>
Увеличить
</button>
{/* Функциональное обновление, если новое состояние зависит от предыдущего */}
<button onClick={() => setCount(prev => prev - 1)}>
Уменьшить
</button>
</div>
);
}
```
2. useEffect
Позволяет выполнять **side effects** в функциональных компонентах: запросы к API, подписки на события, ручное изменение DOM. Заменяет `componentDidMount`, `componentDidUpdate` и `componentWillUnmount`.
```javascript
useEffect(() => {
// Код для выполнения после каждого рендера
console.log('Эффект выполнился');
// Функция очистки (аналог componentWillUnmount)
return () => {
console.log('Очистка эффекта');
};
}, [dep1, dep2]); // Массив зависимостей. Эффект запустится только при их изменении.
```
**Важные варианты:**
* `useEffect(() => {...})` — выполняется после **каждого** рендера.
* `useEffect(() => {...}, [])` — выполняется один раз, после **первого** монтирования (аналог `componentDidMount`).
* `useEffect(() => {...}, [dep])` — выполняется при изменении зависимости `dep`.
useContext
Позволяет подписаться на контекст React, избегая пропс дриллинга (prop drilling). Принимает объект контекста, созданный `React.createContext`, и возвращает его текущее значение.
```javascript
const ThemeContext = React.createContext('light');
function ThemedButton() {
const theme = useContext(ThemeContext); // Получаем значение напрямую
return <button className={theme}>Кнопка</button>;
}
```
🛠 Дополнительные хуки (Additional Hooks)
Эти хуки решают более специфические задачи: оптимизация, работа с refs, управление сложным состоянием.
useReducer
Альтернатива `useState` для управления сложной логикой состояния. Принимает редюсер `(state, action) => newState` и начальное состояние. Похож на Redux в миниатюре.
```javascript
const initialState = { count: 0 };
function reducer(state, action) {
switch (action.type) {
case 'increment': return { count: state.count + 1 };
case 'decrement': return { count: state.count - 1 };
default: throw new Error();
}
}
function Counter() {
const [state, dispatch] = useReducer(reducer, initialState);
return (
<>
Count: {state.count}
<button onClick={() => dispatch({ type: 'decrement' })}>-</button>
<button onClick={() => dispatch({ type: 'increment' })}>+</button>
</>
);
}
```
5. useRef
Создает мутируемый объект, свойство `.current` которого сохраняется между рендерами. Основные use cases:
* Доступ к DOM-элементам.
* Хранение мутируемых значений, которые не должны вызывать ререндер.
```javascript
function TextInputWithFocusButton() {
const inputEl = useRef(null);
const renderCount = useRef(0); // Не вызывает ререндер!
useEffect(() => {
renderCount.current = renderCount.current + 1;
});
const onButtonClick = () => {
inputEl.current.focus(); // Прямой доступ к DOM-ноде
};
return (
<>
<input ref={inputEl} type="text" />
<button onClick={onButtonClick}>Фокус на поле</button>
<p>Компонент отрендерен {renderCount.current} раз</p>
</>
);
}
```
6. useMemo и useCallback
Хуки для **оптимизации производительности**, предотвращающие лишние вычисления и ререндеры дочерних компонентов.
* `useMemo` — кеширует результат вычислений. Пересчитывает только при изменении зависимостей.
* `useCallback` — кеширует саму функцию, а не её значение. Критично для оптимизированных дочерних компонентов, которые зависят от `React.memo`.
```javascript
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
const memoizedCallback = useCallback(() => { doSomething(a, b); }, [a, b]);
```
7. useImperativeHandle
Позволяет кастомизировать значение, которое передается родительскому компоненту при использовании `ref`. Используется редко, в связке с `React.forwardRef`.
useLayoutEffect
Имеет ту же сигнатуру, что и `useEffect`, но выполняется синхронно **после всех мутаций DOM**, но до того, как браузер отрисует изменения. Используется для измерений DOM или синхронных мутаций, чтобы избежать "мерцания".
useDebugValue
Позволяет добавлять кастомные метки для пользовательских хуков в React DevTools. Упрощает отладку.
🧩 Пользовательские хуки (Custom Hooks)
Главная мощь хуков — возможность создавать свои собственные, инкапсулируя и переиспользуя логику с состоянием. Это просто JavaScript-функции, имена которых начинаются с use и которые могут вызывать другие хуки.
// Пользовательский хук для подписки на онлайн-статус друга
function useFriendStatus(friendID) {
const [isOnline, setIsOnline] = useState(null);
useEffect(() => {
function handleStatusChange(status) {
setIsOnline(status.isOnline);
}
ChatAPI.subscribeToFriendStatus(friendID, handleStatusChange);
return () => {
ChatAPI.unsubscribeFromFriendStatus(friendID, handleStatusChange);
};
}, [friendID]); // Переподписка при смене friendID
return isOnline;
}
// Использование в компоненте
function FriendListItem({ friend }) {
const isOnline = useFriendStatus(friend.id); // Логика переиспользуется!
return (
<li style={{ color: isOnline ? 'green' : 'black' }}>
{friend.name}
</li>
);
}
🎯 Правила хуков (Rules of Hooks)
При работе с хуками необходимо строго соблюдать два правила:
- Вызывайте хуки только на верхнем уровне. Не вызывайте их внутри циклов, условий или вложенных функций.
- Вызывайте хуки только из React-функций или из пользовательских хуков.
Для автоматического контроля этих правил используется линтер ESLint с плагином eslint-plugin-react-hooks.
Итог: Хуки — это фундаментальная и неотъемлемая часть современной экосистемы React. Они обеспечивают более прямой способ использования возможностей React (состояние, жизненный цикл, контекст) через функции, значительно улучшая композицию, читаемость и тестируемость кода. Понимание и грамотное применение всех типов хуков, особенно useState, useEffect, useMemo/useCallback и умение создавать custom hooks, является ключевым навыком для профессионального Frontend-разработчика на React.