Урок 02

useState: подробно

useState — базовый хук для локального состояния компонента.

Синтаксис

const [value, setValue] = useState(initialValue);

Хук возвращает массив из двух элементов: текущее значение и функция обновления.

Начальное значение

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);

Обновление

Прямое значение

setCount(5);
setName('Алиса');

Функция

setCount((prev) => prev + 1);

Функция получает предыдущее значение и возвращает новое. Используй, когда новое значение зависит от предыдущего.

Почему функция важна

React батчит обновления. Если написать два прямых вызова, они оба прочитают одно и то же count:

// Не увеличит на 2
setCount(count + 1);
setCount(count + 1);

Функциональная форма решает проблему:

// Увеличит на 2
setCount((c) => c + 1);
setCount((c) => c + 1);

Объекты и массивы

Состояние иммутабельно. Не мутируй объект или массив — создавай новый.

Объект:

const [user, setUser] = useState({ name: 'Алиса', age: 25 });

// Неправильно
user.age = 26;

// Правильно
setUser({ ...user, age: 26 });

Массив:

const [items, setItems] = useState<string[]>([]);

// Добавить в конец
setItems([...items, 'новый']);

// Добавить в начало
setItems(['новый', ...items]);

// Удалить
setItems(items.filter((i) => i !== 'удалить'));

// Обновить элемент
setItems(items.map((i) => (i === 'старый' ? 'новый' : i)));

Ленивая инициализация

Если начальное значение вычисляется долго, передай функцию:

const [data, setData] = useState(() => {
    return JSON.parse(localStorage.getItem('data') ?? '[]');
});

Функция вызовется один раз при первом рендере.

Сброс состояния

Если нужно сбросить состояние — установи начальное значение:

setForm({ name: '', email: '' });

Обновление вложенных объектов

const [user, setUser] = useState({
    name: 'Алиса',
    address: { city: 'Москва', zip: '101000' },
});

setUser({
    ...user,
    address: {
        ...user.address,
        city: 'Питер',
    },
});

Несколько состояний или одно

Раздельные:

const [name, setName] = useState('');
const [email, setEmail] = useState('');
const [age, setAge] = useState(0);

Одно:

const [form, setForm] = useState({ name: '', email: '', age: 0 });

Раздельные — если поля меняются независимо. Одно — если меняются вместе и логически связаны.

Итоги

  • useState возвращает значение и функцию
  • Функция обновления — когда новое зависит от предыдущего
  • Стейт не мутируется, а заменяется
  • Ленивая инициализация — через функцию