useState: состояние компонента
Состояние — это данные, которые меняются со временем и влияют на отображение. Когда состояние меняется, React перерисовывает компонент.
Базовый useState
import { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>Значение: {count}</p>
<button onClick={() => setCount(count + 1)}>+1</button>
</div>
);
}
useState возвращает массив из двух элементов:
- текущее значение
- функция для его обновления
Начальное значение
const [count, setCount] = useState(0); // число
const [name, setName] = useState(''); // строка
const [active, setActive] = useState(false); // булево
const [items, setItems] = useState<string[]>([]); // массив
const [user, setUser] = useState<User | null>(null); // объект или null
Обновление через функцию
Если новое значение зависит от предыдущего — используй функцию:
<button onClick={() => setCount((prev) => prev + 1)}>+1</button>
Это важно при нескольких обновлениях подряд: React применит все функции к актуальному значению.
Объекты в состоянии
Стейт нельзя мутировать — нужно создавать новый объект:
const [user, setUser] = useState({ name: 'Алиса', age: 25 });
// Неправильно
user.name = 'Боб';
// Правильно
setUser({ ...user, name: 'Боб' });
Массивы в состоянии
const [items, setItems] = useState<string[]>([]);
// Добавить
setItems([...items, 'новый']);
// Удалить
setItems(items.filter((item) => item !== 'ненужный'));
// Обновить элемент
setItems(items.map((item) =>
item === 'старый' ? 'новый' : item
));
Несколько состояний
const [name, setName] = useState('');
const [email, setEmail] = useState('');
const [age, setAge] = useState(0);
Если полей много и они логически связаны — можно объединить:
const [form, setForm] = useState({
name: '',
email: '',
age: 0,
});
setForm({ ...form, name: 'Алиса' });
Ленивая инициализация
Если начальное значение вычисляется долго, передай функцию:
const [data, setData] = useState(() => {
return JSON.parse(localStorage.getItem('data') ?? '[]');
});
Функция вызовется только один раз.
Состояние и рендер
Изменение состояния асинхронно. React батчит несколько обновлений в один рендер:
setCount(count + 1);
setCount(count + 1); // не сработает как ожидается
Правильно:
setCount((prev) => prev + 1);
setCount((prev) => prev + 1); // увеличит на 2
useState с типом
const [user, setUser] = useState<User | null>(null);
const [status, setStatus] = useState<'idle' | 'loading' | 'success' | 'error'>('idle');
Итоги
useStateвозвращает значение и функцию обновления- Обновление через функцию — когда зависит от предыдущего
- Стейт не мутируется, а заменяется
- Несколько вызовов
setStateбатчатся - Начальное значение можно вычислять лениво