Объекты и массивы в состоянии
В состоянии можно хранить объекты и массивы — например, весь список задач. Главное правило: их нельзя менять на месте. React сравнивает старое и новое значение, и если это тот же самый массив, он решит, что ничего не изменилось. Поэтому каждый раз создают новую копию с изменениями.
Массив задач в состоянии
Перенесите задачи в состояние в src/App.jsx:
// src/App.jsx
import { useState } from 'react';
import TodoList from './components/TodoList.jsx';
const initialTodos = [
{ id: 1, text: 'Купить молоко', done: false },
{ id: 2, text: 'Позвонить Олегу', done: true },
];
export default function App() {
const [todos, setTodos] = useState(initialTodos);
return <TodoList todos={todos} />;
}Страница пока выглядит как раньше, но теперь список можно менять.
Добавление
Новый массив собирают оператором расширения ...: все старые элементы плюс новый.
// src/App.jsx
function handleAdd() {
const todo = { id: crypto.randomUUID(), text: 'Новая задача', done: false };
setTodos([...todos, todo]);
}
// в разметке:
<button onClick={handleAdd}>Добавить</button>Каждый клик добавляет в конец списка пункт «Новая задача». crypto.randomUUID() — встроенная функция браузера, она даёт уникальную строку для id.
Удаление
Удаляют через filter — он возвращает новый массив без лишнего элемента:
// src/App.jsx
function handleDelete(id) {
setTodos(todos.filter((todo) => todo.id !== id));
}Изменение элемента
Чтобы отметить задачу выполненной, через map создают новый массив, где нужная задача заменена новым объектом:
// src/App.jsx
function handleToggle(id) {
setTodos(
todos.map((todo) => (todo.id === id ? { ...todo, done: !todo.done } : todo)),
);
}{ ...todo, done: !todo.done } копирует все поля задачи и заменяет только done. Остальные задачи остаются прежними объектами.
Как вызвать handleDelete и handleToggle из TodoItem, разберём в уроке про подъём состояния.
Объект в состоянии
С объектом всё так же: копия плюс изменённое поле.
// src/components/Profile.jsx
import { useState } from 'react';
export default function Profile() {
const [user, setUser] = useState({ name: 'Анна', city: 'Рига' });
return (
<button onClick={() => setUser({ ...user, city: 'Берлин' })}>
{user.name} из города {user.city}
</button>
);
}После клика кнопка покажет «Анна из города Берлин».
Шпаргалка
| Действие | Вместо | Пишите |
|---|---|---|
| Добавить | push | [...arr, item] |
| Удалить | splice | arr.filter(...) |
| Изменить | arr[i] = x | arr.map(...) |
| Сортировать | sort на месте | [...arr].sort(...) или toSorted |
| Поле объекта | obj.x = 1 | { ...obj, x: 1 } |
Частая ошибка
Изменение массива на месте и передача того же массива в сеттер не обновляет страницу:
// Неправильно: React видит тот же массив и не перерисовывает.
todos.push(todo);
setTodos(todos);
// Правильно:
setTodos([...todos, todo]);Если список «не обновляется», проверьте, не используются ли push, splice, sort или присваивание полю.