Хуки React
Состояние и побочные эффекты
Что такое хук
Хук — функция, которая даёт функциональному компоненту доступ к возможностям React: состоянию, эффектам, контексту. Все хуки начинаются с use, и это не соглашение, а требование линтера.
useState: состояние компонента
Самый нужный хук. Возвращает пару: текущее значение и функцию для его изменения.
import { useState } from "react";
function Counter() {
const [count, setCount] = useState(0);
return (
<button onClick={() => setCount(count + 1)}>
Нажато {count} раз
</button>
);
}
Вызов setCount не меняет переменную напрямую — он просит React перерисовать компонент с новым значением. Прямое изменение count = 5 ничего не даст.
Функциональное обновление. Если новое значение зависит от предыдущего, передайте функцию: setCount(c => c + 1). Так вы не попадёте в ситуацию, когда несколько обновлений подряд теряются.
Сложное состояние. Для объектов и массивов создавайте новую копию: setUser({...user, name: "Анна"}). Мутация той же ссылки не вызовет перерисовку.
useEffect: побочные эффекты
Запросы к API, подписки, таймеры, работа с document — всё, что выходит за пределы отрисовки. Эффект запускается после того, как компонент появился на экране.
import { useEffect, useState } from "react";
function Posts() {
const [posts, setPosts] = useState([]);
useEffect(() => {
fetch("/api/posts")
.then(r => r.json())
.then(setPosts);
}, []);
return <ul>{posts.map(p => <li key={p.id}>{p.title}</li>)}</ul>;
}
Массив зависимостей — главное, что нужно понять:
-
[]— эффект выполнится один раз при монтировании. -
[id]— заново при измененииid. - без второго аргумента — после каждой отрисовки, что почти всегда ошибка.
Очистка. Если эффект создаёт подписку или таймер, верните функцию очистки — React вызовет её при размонтировании:
useEffect(() => {
const id = setInterval(tick, 1000);
return () => clearInterval(id);
}, []);
Правила хуков
Два правила, которые нельзя нарушать:
- Вызывайте хуки только на верхнем уровне компонента — не внутри условий, циклов и вложенных функций.
- Вызывайте их только из компонентов React или из других хуков.
Причина простая: React различает хуки по порядку вызова. Условный вызов ломает этот порядок и приводит к перемешиванию состояния.
Частые ошибки
- Бесконечный цикл. Эффект без массива зависимостей меняет состояние, что вызывает новую отрисовку и новый эффект.
- Забытые зависимости. Внутри эффекта используется переменная, которой нет в массиве — эффект работает со старым значением.
- Мутация состояния.
items.push(x)вместоsetItems([...items, x])— компонент не перерисуется. - Хук в условии.
if (isOpen) { useEffect(...) }— нарушение правил, состояние поедет.
Нужен сайт на React, а не статья?
Соберу интерфейс под ключ: компоненты, состояние, запросы к API, роутинг, сборка Vite и деплой. С 2009 года, по договору, с поддержкой после запуска.
Полезно по теме: React с нуля, установка React, про Django.