Перейти к содержанию
Innovialabs

Хуки React: useState, useEffect, useRef и другие на примерах

Практика3 мин

Коротко

Хуки — это функции, которые дают компоненту состояние (useState), побочные эффекты (useEffect) и ссылки (useRef); вызывайте их только на верхнем уровне и честно указывайте зависимости.

Что такое хуки и зачем они нужны

Хуки — это функции, которые позволяют функциональному компоненту хранить состояние, реагировать на изменения и работать с DOM. Они заменили классовые компоненты и сделали логику переиспользуемой: общий код выносится в свой хук, а не размазывается по жизненному циклу.

Основной набор, который нужен почти в каждом проекте:

ХукДля чего
useStateЛокальное состояние, изменение которого вызывает перерисовку
useEffectСинхронизация с внешним миром: подписки, таймеры, запросы
useRefСсылка на DOM-элемент или значение, которое не вызывает ререндер
useMemo / useCallbackКеширование вычислений и функций между рендерами
useContextЧтение значения из контекста без передачи пропсов

useState: состояние компонента

const [count, setCount] = useState(0);

// Новое значение зависит от предыдущего — используйте функцию
setCount(prev => prev + 1);

Важные моменты:

  • Состояние неизменяемо. Для объектов и массивов создавайте копию: setUser({ ...user, name }), а не user.name = name.
  • Обновление асинхронно. Сразу после setCount переменная count в текущем рендере остаётся старой.
  • Дорогое начальное значение передавайте функцией: useState(() => parse(data)) — она вызовется один раз.

useEffect и массив зависимостей

useEffect запускает код после отрисовки. Второй аргумент определяет, когда эффект повторяется:

  • без массива — после каждого рендера;
  • [] — один раз после монтирования;
  • [userId] — при изменении userId.
useEffect(() => {
  const controller = new AbortController();
  fetch(`/api/users/${userId}`, { signal: controller.signal })
    .then(r => r.json())
    .then(setUser)
    .catch(() => {});
  return () => controller.abort(); // очистка
}, [userId]);

Функция, которую возвращает эффект, — очистка. Она вызывается перед следующим запуском и при размонтировании. Здесь отменяйте запросы, снимайте подписки и останавливайте таймеры.

Типичные ошибки с useEffect

  • Пропущенные зависимости. Если эффект использует переменную, она должна быть в массиве. Включите правило react-hooks/exhaustive-deps в ESLint — оно ловит это автоматически.
  • Бесконечный цикл. Эффект меняет состояние, от которого сам зависит, или в зависимостях объект, создаваемый заново в каждом рендере.
  • Эффект для вычислений. Если значение выводится из пропсов или состояния, считайте его прямо в теле компонента, без useEffect и лишнего useState.
  • Нет очистки. Подписки и интервалы без очистки приводят к утечкам и двойным обработчикам.
  • Гонка запросов. Без отмены ответ на старый запрос может прийти позже нового и перезаписать данные.

useRef: DOM и значения без ререндера

const inputRef = useRef(null);
// <input ref={inputRef} />
inputRef.current.focus();

ref.current можно менять, и это не вызывает перерисовку. Поэтому useRef подходит для хранения id таймера, предыдущего значения или флага, который не нужно показывать на экране.

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

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

Свои хуки

Свой хук — это функция с именем на use, внутри которой вызываются другие хуки. Он выносит повторяющуюся логику:

function useDebounce(value, delay) {
  const [debounced, setDebounced] = useState(value);
  useEffect(() => {
    const id = setTimeout(() => setDebounced(value), delay);
    return () => clearTimeout(id);
  }, [value, delay]);
  return debounced;
}

Каждый компонент, вызвавший хук, получает своё состояние — хуки делят логику, а не данные.

Частые вопросы

В StrictMode React намеренно монтирует, размонтирует и снова монтирует компонент, чтобы проверить корректность очистки. В продакшене эффект запустится один раз. Если двойной запуск что-то ломает — значит, не хватает очистки.

Поможем с этим

Если хотите не разбираться самим, а получить результат — этим мы занимаемся каждый день.

Обсудить проект

Читайте также

Есть идея или задача? Расскажите нам

Ответим в течение рабочего дня и предложим решение. Консультация бесплатная.