Видеоуроки, интерактивный редактор и сохранение прогресса — бесплатно, сразу после входа.
ВойтиСоздать аккаунт — бесплатноЗакончили урок?
Войдите, чтобы отмечать прогресс
В этом решении мы создаём полноценное приложение для управления задачами с добавлением, отметкой выполнения и удалением.
Мы храним массив объектов в состоянии. Каждый объект представляет одну задачу и содержит три поля: id (уникальный идентификатор), text (текст задачи) и completed (выполнена ли задача). Начальные значения позволяют сразу увидеть, как работает приложение.
Отдельное состояние хранит текст, который пользователь вводит в поле. Это состояние очищается после добавления задачи, чтобы поле было готово для ввода следующей.
Метод trim() удаляет пробелы в начале и конце строки. Если после этого строка пустая, функция завершается с помощью return - пустые задачи не добавляются. Это предотвращает создание задач из одних пробелов.
Date.now() возвращает текущее время в миллисекундах с 1 января 1970 года. Это число всегда уникально, потому что время постоянно идёт вперёд. Мы используем его как простой способ создать уникальный id для новой задачи.
Оператор ... (spread) разворачивает массив todos в отдельные элементы. Затем мы добавляем newTodo в конец. Результат - новый массив, который содержит все старые задачи плюс новую. React видит, что это новый массив, и перерисовывает компонент. Важно не использовать push - он мутирует исходный массив, что нарушает правила React.
После добавления задачи мы очищаем поле ввода, устанавливая пустую строку. Это улучшает пользовательский опыт - поле готово для ввода новой задачи, и не нужно стирать старый текст вручную.
Метод map проходит по каждой задаче и возвращает новый массив. Для задачи с нужным id мы создаём новый объект с помощью spread оператора { ...todo }, который копирует все поля, и затем перезаписываем completed на противоположное значение. Для остальных задач возвращаем их без изменений. Это создаёт новый массив с изменённой задачей.
Метод filter создаёт новый массив, содержащий только те элементы, для которых функция вернула true. Мы оставляем все задачи, у которых id не совпадает с удаляемым. Задача с нужным id не попадает в новый массив - она удалена.
Значение input полностью контролируется React через состояние. Атрибут value устанавливает отображаемый текст, а onChange обновляет состояние при каждом вводе символа. e.target.value содержит текущее значение поля. Это называется "контролируемый компонент" - React является единственным источником истины.
Мы слушаем событие onKeyUp и проверяем, была ли нажата клавиша Enter. Если да, вызываем addTodo. Оператор && работает как краткая форма условия - правая часть выполняется только если левая истинна. Это позволяет добавлять задачи без клика на кнопку.
Метод map преобразует каждую задачу в элемент <li>. Атрибут key с уникальным id помогает React отслеживать, какие элементы изменились. Без key React не сможет эффективно обновлять список.
Класс completed добавляется только для выполненных задач. CSS использует этот класс для зачёркивания текста или изменения цвета. Это визуально показывает, какие задачи уже сделаны.
Мы не храним количество в состоянии - вычисляем его на основе массива todos. filter отбирает только выполненные задачи, а length даёт их количество. Эти значения автоматически обновляются при каждом рендере, когда меняется todos.
Когда задач нет, вместо пустого списка показываем приятное сообщение. Тернарный оператор проверяет длину массива - если 0, показываем заглушку, иначе - список. Это делает интерфейс более дружелюбным.
Статистика показывается только когда есть задачи. Оператор && рендерит правую часть только если левая истинна. Когда список пуст, статистика не имеет смысла, поэтому мы её скрываем.