Encodera

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

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

Оглавление

Вычисляемые значения

Не всё, что меняется на экране, нужно хранить в состоянии. Если значение можно получить из пропсов или другого состояния, его вычисляют прямо при отрисовке. Такое значение называют вычисляемым (производным). Чем меньше состояния, тем меньше мест, где данные могут разойтись.

Счётчик задач

Сколько задач осталось — это не отдельное состояние, а результат подсчёта по массиву todos:

// src/App.jsx
import { useState } from 'react';
import TodoList from './components/TodoList.jsx';
 
export default function App() {
  const [todos, setTodos] = useState([
    { id: 1, text: 'Купить молоко', done: false },
    { id: 2, text: 'Позвонить Олегу', done: true },
  ]);
 
  const left = todos.filter((todo) => !todo.done).length;
 
  return (
    <>
      <p>Осталось задач: {left}</p>
      <TodoList todos={todos} />
    </>
  );
}

На странице будет «Осталось задач: 1». При каждом изменении todos React снова вызовет App, и left пересчитается сам.

Фильтр списка

В состоянии хранят только выбор пользователя — какой фильтр нажат. Сам отфильтрованный список вычисляют:

// src/App.jsx
const [filter, setFilter] = useState('all');
 
const visible = todos.filter((todo) => {
  if (filter === 'active') return !todo.done;
  if (filter === 'done') return todo.done;
  return true;
});
 
// в разметке:
<button onClick={() => setFilter('all')}>Все</button>
<button onClick={() => setFilter('active')}>Активные</button>
<button onClick={() => setFilter('done')}>Выполненные</button>
<TodoList todos={visible} />

Кнопки переключают фильтр, а список под ними меняется. Добавление или удаление задачи тоже сразу отразится в отфильтрованном списке.

Как решить, нужно ли состояние

ВопросЕсли да
Значение приходит из пропсов?Не состояние, используйте проп
Его можно вычислить из другого состояния?Не состояние, вычисляйте
Оно не меняется со временем?Не состояние, обычная константа
Ничего из этого?Это состояние

Для списка задач состоянием будут только todos и filter. Число оставшихся задач, текст «Нет задач» и видимый список — вычисляемые.

Дорогие вычисления

Подсчёт по массиву из сотни задач занимает доли миллисекунды, так что беспокоиться о скорости не нужно. Если вычисление действительно тяжёлое, его можно запомнить хуком useMemo — о нём отдельный урок.

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

Копия вычисляемого значения в отдельном состоянии быстро устаревает:

// Неправильно: left нужно вручную обновлять при каждом изменении todos.
const [todos, setTodos] = useState(initialTodos);
const [left, setLeft] = useState(1);
 
// Правильно:
const left = todos.filter((todo) => !todo.done).length;

Добавили задачу и забыли вызвать setLeft — на странице неверное число. Вычисляемое значение всегда совпадает с данными.

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

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