Хуки React это функции с именами, начинающимися на use, которые позволяют функциональному компоненту использовать возможности React: useState, чтобы запомнить значение, useEffect, чтобы выполнить код после рендеринга, useRef, чтобы держать узел DOM, useContext, чтобы прочитать общие данные. Вы вызываете их в начале компонента, а React сохраняет их значения между рендерами.
Здесь вместе работают четыре хука. useState хранит текст, useRef указывает на поле, чтобы кнопка могла поставить на него фокус, useMemo хранит отфильтрованный список, пока не изменится запрос, а useEffect выводит сообщение после каждого рендера, в котором запрос изменился. Наберите an и смотрите в Console: по одной строке на нажатие клавиши, после обновления списка.
Зачем нужны хуки
До React 16.8 компонент, которому нужны были состояние или код жизненного цикла, должен был быть классом. Логика одной функции была разбросана по componentDidMount, componentDidUpdate и componentWillUnmount, а чтобы поделиться ею между компонентами, нужны были миксины (которые так и не заработали с синтаксисом классов), компоненты высшего порядка или render props, и всё это оборачивало дерево в лишние слои.
// The class way: one feature, three methods
class Clock extends React.Component {
state = { now: new Date() };
componentDidMount() {
this.id = setInterval(() => this.setState({ now: new Date() }), 1000);
}
componentWillUnmount() {
clearInterval(this.id);
}
render() {
return <p>{this.state.now.toLocaleTimeString()}</p>;
}
}
С хуками та же функция живёт в одном месте: эффект запускает таймер, а его очистка останавливает.
Скройте часы, и Console выведет timer stopped: React выполнил очистку, когда Clock ушёл с экрана. Покажите снова, и запустится свежий таймер. Классовые компоненты по-прежнему работают в React 19, но новый код использует хуки.
Все встроенные хуки
React 19.2 группирует хуки по тому, что они дают компоненту. Первые две группы вы будете использовать каждый день, а остальные, когда этого потребует конкретная задача.
| Хук | Что он даёт | Страница |
|---|---|---|
useState | Значение, которое переживает рендеры, и сеттер, который рендерит снова | useState |
useReducer | Состояние, которое обновляется функцией-редьюсером и отправленными действиями | useReducer |
useContext | Значение, предоставленное родителем, без передачи пропсов | useContext |
useRef | Изменяемая коробка, которая переживает рендеры, часто узел DOM | useRef |
useImperativeHandle | Выбирает, что родитель видит через ваш ref | forwardRef |
useEffect | Код, который обычно выполняется после отрисовки: таймеры, подписки, загрузка данных | useEffect |
useLayoutEffect | Код, который выполняется после обновления DOM, но до отрисовки | useLayoutEffect |
useInsertionEffect | Выполняется раньше layout-эффектов, для библиотек CSS-in-JS | |
useEffectEvent | Функция, которую может вызывать эффект и которая всегда видит последние пропсы и состояние | useEffect |
useMemo | Кэширует вычисленное значение между рендерами | useMemo |
useCallback | Кэширует функцию между рендерами | useCallback |
useTransition | Помечает обновление как несрочное и сообщает, пока оно ожидает | useTransition |
useDeferredValue | Копия значения, которая отстаёт во время тяжёлых рендеров | useDeferredValue |
useId | Уникальный id, который совпадает на сервере и на клиенте | useId |
useSyncExternalStore | Подписка на хранилище, которое живёт вне React | useSyncExternalStore |
useDebugValue | Подпись для пользовательского хука в React DevTools | |
use | Читает промис или контекст и может стоять внутри условия | use |
useActionState | Состояние, которое обновляет действие формы, с флагом ожидания | useActionState |
useOptimistic | Показывает ожидаемый результат до ответа сервера | useOptimistic |
useFormStatus | Состояние ожидания родительской формы (из react-dom) |
use, useActionState, useOptimistic и useFormStatus появились в React 19, а useEffectEvent стал стабильным в 19.2. Все остальные хуки из списка работают и в React 18.
Состояние вызывает рендер, рефы нет
Не каждый хук вызывает рендер. useState и useReducer вызывают: измените их значение, и React снова нарисует компонент. useRef даёт объект, поле current которого можно свободно менять, и React никогда не перерендеривает из-за него. Поэтому это правильное место для id таймера, предыдущего значения или счётчика, который экран не показывает.
useReducer хранит корзину, а useState хранит заметку; оба вызывают рендер при изменении, а эффект выводит по строке на каждый рендер. Эффект также меняет commits.current, но это изменение никогда не вызывает собственного рендера, поэтому лог не зацикливается. Счётчик обновляется в эффекте, а не в теле компонента, потому что тело не должно ничего менять во время рендера.
Правила хуков
Каждый хук подчиняется двум правилам:
- Вызывайте хуки на верхнем уровне компонента, никогда внутри условия, цикла или вложенной функции.
- Вызывайте хуки только из функциональных компонентов или из собственных пользовательских хуков.
React не знает хуки по имени. Он знает их по порядку вызова и ожидает, что этот порядок будет одинаковым при каждом рендере. Хук внутри if сдвинул бы все хуки после него. Страница о правилах хуков показывает, что ломается и как это исправить. use единственное исключение: его можно вызывать внутри условия.
Ваш первый пользовательский хук
Когда двум компонентам нужна одна и та же логика с состоянием, перенесите её в функцию, имя которой начинается с use. Эта функция может вызывать любой другой хук. Каждый компонент, который её вызывает, получает собственное состояние.
Оба счётчика используют один и тот же хук, но клик по одному не трогает другой: пользовательский хук делится логикой, а не состоянием. Добавьте в useCounter функцию decrement и кнопку, которая её вызывает, и её получат сразу оба счётчика. Больше шаблонов (useToggle, useDebounce, useLocalStorage) на странице о пользовательских хуках.
Какой хук выбрать
- Экран должен меняться при изменении значения:
useStateилиuseReducer, когда одно и то же состояние обновляют многие события. - Нужно общаться с чем-то вне React (таймером, подпиской, запросом):
useEffect. - Нужен узел DOM или значение, которое экран не показывает:
useRef. - Многим компонентам глубоко в дереве нужно одно и то же значение:
useContext. - Рендер медленный из-за одного вычисления или из-за того, что мемоизированный дочерний компонент перерендеривается:
useMemoиuseCallback. React Compiler может добавить эту мемоизацию за вас, но писать её вручную по-прежнему можно, и это всё ещё распространено. - Ввод кажется заторможенным, потому что обновление за ним тяжёлое:
useTransitionилиuseDeferredValue.
Часто задаваемые вопросы
Что такое хуки в React?
Хуки это функции с именами, начинающимися на use, которые позволяют функциональному компоненту использовать возможности React: useState для состояния, useEffect для побочных эффектов, useContext для контекста, useRef для значений, которые переживают рендеры и не вызывают их, и другие.
Зачем в React добавили хуки?
До хуков (React 16.8) состояние и методы жизненного цикла были только в классовых компонентах, а чтобы делиться логикой с состоянием, нужны были миксины, компоненты высшего порядка или render props. Хуки помещают эту логику в обычные функции, которые можно вызывать из любого функционального компонента и которыми можно делиться как пользовательскими хуками.
Сколько хуков в React?
React 19.2 поставляет около двадцати встроенных хуков в пакете react, плюс useFormStatus в react-dom. Большинство приложений каждый день используют несколько: useState, useEffect, useRef, useContext, useMemo и useCallback.
Можно ли использовать хуки в классовых компонентах?
Нет. Хуки работают только внутри функциональных компонентов и других хуков. При этом классовый компонент можно рендерить рядом с функциональными, а класс может рендерить функциональный компонент, который использует хуки.
Что такое пользовательский хук?
Ваша собственная функция, имя которой начинается с use и которая вызывает другие хуки. Она позволяет нескольким компонентам переиспользовать одну и ту же логику с состоянием, при этом каждый вызывающий её компонент получает собственное отдельное состояние.