Menu

Хуки React: каждый хук с живыми примерами

Хук это функция, имя которой начинается с use и которая позволяет компоненту использовать возможность React: состояние, контекст, рефы или эффекты. Все встроенные хуки, сгруппированные по назначению, два правила, которым подчиняется каждый хук, и как написать свой.

На этой странице есть исполняемые редакторы: меняйте, запускайте и сразу видите результат.

Хуки 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Изменяемая коробка, которая переживает рендеры, часто узел DOMuseRef
useImperativeHandleВыбирает, что родитель видит через ваш refforwardRef
useEffectКод, который обычно выполняется после отрисовки: таймеры, подписки, загрузка данныхuseEffect
useLayoutEffectКод, который выполняется после обновления DOM, но до отрисовкиuseLayoutEffect
useInsertionEffectВыполняется раньше layout-эффектов, для библиотек CSS-in-JS
useEffectEventФункция, которую может вызывать эффект и которая всегда видит последние пропсы и состояниеuseEffect
useMemoКэширует вычисленное значение между рендерамиuseMemo
useCallbackКэширует функцию между рендерамиuseCallback
useTransitionПомечает обновление как несрочное и сообщает, пока оно ожидаетuseTransition
useDeferredValueКопия значения, которая отстаёт во время тяжёлых рендеровuseDeferredValue
useIdУникальный id, который совпадает на сервере и на клиентеuseId
useSyncExternalStoreПодписка на хранилище, которое живёт вне ReactuseSyncExternalStore
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, но это изменение никогда не вызывает собственного рендера, поэтому лог не зацикливается. Счётчик обновляется в эффекте, а не в теле компонента, потому что тело не должно ничего менять во время рендера.

Правила хуков

Каждый хук подчиняется двум правилам:

  1. Вызывайте хуки на верхнем уровне компонента, никогда внутри условия, цикла или вложенной функции.
  2. Вызывайте хуки только из функциональных компонентов или из собственных пользовательских хуков.

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 и которая вызывает другие хуки. Она позволяет нескольким компонентам переиспользовать одну и ту же логику с состоянием, при этом каждый вызывающий её компонент получает собственное отдельное состояние.

Иллюстрация языков программирования Coddy

Учитесь программировать с Coddy

НАЧАТЬ