Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Оглавление

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

В состоянии можно хранить объекты и массивы — например, весь список задач. Главное правило: их нельзя менять на месте. 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]
Удалитьsplicearr.filter(...)
Изменитьarr[i] = xarr.map(...)
Сортироватьsort на месте[...arr].sort(...) или toSorted
Поле объектаobj.x = 1{ ...obj, x: 1 }

Частая ошибка

Изменение массива на месте и передача того же массива в сеттер не обновляет страницу:

// Неправильно: React видит тот же массив и не перерисовывает.
todos.push(todo);
setTodos(todos);
 
// Правильно:
setTodos([...todos, todo]);

Если список «не обновляется», проверьте, не используются ли push, splice, sort или присваивание полю.

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.