Рассмотрим, как с нуля создать приложение Todo (список дел) с помощью React, библиотеки JavaScript для разработки пользовательских интерфейсов, используя синтаксис ES6 и хуки React. Это будет базовое приложение с полем для ввода элемента Todo и кнопкой рядом с каждым элементом, предназначенной для его удаления.
Кроме того, мы будем использовать хук useState
из React для сохранения состояния приложения и некоторые продвинутые функции JavaScript, такие как map()
, массив spread
, ternary operator
и метод filter()
. Цель этого руководства — помочь новичкам начать работу с React.

Полный код проекта можно найти здесь.
Необходимые условия
Установите следующие программы.
- NodeJS и NPM (загрузить здесь).
- Create React App (руководство по установке).
Установка
Для начала создадим новое приложение React с помощью инструмента командной строки create-react-app
. Мы создадим новый каталог, а затем — приложение React внутри него. Для выполнения задачи можно использовать следующие команды:
1 $ mkdir react-todo-app
2 $ cd react-todo-app
3 $ create-react-app ./
Чтобы начать работу с нуля, удалим все из папки src
, кроме файлов App.js
и index.js
. Внутри App.js
удалите все, кроме родительского заголовка, и добавьте к нему h1
-элемент (<h1> React Todo App </h1>
). Чтобы увидеть приложение в действии, запустите команду npm start
в окне терминала в корне проекта.
Этот коммит на GitHub показывает изменения до настоящего момента.
CSS и стиль
Мы создали простое приложение, содержащее только один элемент h1
. Прежде чем двигаться дальше, добавим в него несколько основных стилей. Создайте файл App.css
в каталоге src
и импортируйте его в файл App.js
. Добавьте стили из этой ссылки в файл App.css
.
Можете сравнить свой проект с этим коммитом на GitHub.
Создание начального макета
Начнем с простого макета, содержащего поле input
и button
для добавления нового элемента Todo. В файле App.js
создайте новый div
с классом input-wrapper
внутри родительского div
.

Создание и отображение элементов Todo
1. Создание нового элемента Todo
Чтобы отслеживать состояние внутри компонента React, мы будем использовать хук useState
. Он принимает начальное значение состояния и возвращает массив с двумя значениями:
- функция
getter
, которая отображает текущее значение определенного состояния; - функция
setter
, обновляющая состояние.
Мы будем использовать useState
в этом приложении для отслеживания каждого нового элемента Todo и списка Todo. Но сначала мы импортируем хук useState
в файл App.js
следующим образом:
import { useState } from "react";
Для начала создадим состояние todo
(функция getter
) со значением undefined
и метод setTodo
(функция setter
) для установки значения текущего элемента todo
.
const [todo, setTodo] = useState("");
Поля ввода снабжены обработчиком событий onChange
, который срабатывает каждый раз, когда значение поля изменяется. Этот обработчик событий предоставляет не само значение, а объект event
, который можно использовать для получения значения с помощью event.target.value
.
Setter
-функция setTodo
будет присоединена к обработчику событий onChange
, который передает значение входа в setter
-функцию через event.target.value
. Значение из входа впоследствии используется методом setter
для обновления состояния todo
.

Проект можно сравнить с этим коммитом на Github.
2. Добавление элемента Todo в список
После создания нового Todo нужно добавить его в список. Мы будем действовать так же, как и при создании нового элемента Todo. Нам нужно создать новый хук useState
для отслеживания состояния массива Todos
и добавить в него новые элементы.
const [todos, setTodos] = useState([]);
Далее создадим onClick
-функцию addTodo
для добавления элемента todo
в массив Todos
. Эта функция будет срабатывать при нажатии на кнопку Add
.
Важно помнить, что состояние не должно изменяться напрямую. Поэтому необходимо сделать копию массива Todos
, прежде чем добавлять в него элементы todo
. Чтобы скопировать массив Todos
и добавить в него элемент todo
, воспользуемся оператором массивов spread
.
const addTodo = () => {
setTodos([...todos, todo]);
};
При добавлении нового элемента Todo в список нужно убедиться в том, что значение не будет пустым . Это можно сделать с помощью оператора if
в функции addTodo
, который проверяет наличие пустого значения. После того, как значение входа добавляется в список Todos
, нужно очистить поле ввода.

Наконец, мы передаем эту функцию в обработчик onClick
кнопки Add
.
<button className="add-button" onClick={addTodo}>
Этот коммит на GitHub отражает полный код до настоящего момента.
3. Отображение элементов Todo
Мы создадим ul
с классом todo-list
для отображения записей из списка Todos
. Будем перебирать элементы в массиве методом map()
и затем отображать их как li
в элементе ul
. Вызовем метод map()
с двумя аргументами: значением текущего обрабатываемого элемента в массиве и его индексом. В данном случае index
будет использоваться в качестве ключа li
.
Для каждого элемента списка Todos
создадим новый div
с классом todo
. Этот div
будет содержать элемент li
и кнопку delete
для его удаления.

Прежде чем отображать список, нужно убедиться в том, что он не пуст. Для отображения элементов списка будет использоваться тернарный оператор. Если список окажется пустым, мы получим соответствующее сообщение.

Проект на данном этапе можно сверить с этим коммитом на GitHub.
Удаление элементов Todo
Начнем с создания функции onClick
, которая срабатывает при нажатии на кнопку удаления. В этой функции удаления будет использоваться метод filter()
, который создает новый массив со всеми записями, удовлетворяющими заданным критериям. В данном примере мы создадим новый массив Todos
, содержащий все элементы, кроме удаляемого. В конце нужно будет обновить состояние с помощью вновь созданных Todos
.

Передаем метод deleteTodo
в обработчик onClick
кнопки delete
.

С кодом до этого момента можно свериться здесь.
Рефакторинг кода
Чтобы собирать введенные данные и показывать элементы Todos
, можно перестроить приложение, создав два независимых компонента — TodoInput
и TodoList
. В каталоге src
создайте два файла: TodoInput.js
и TodoList.js
. Наполните каждый из них содержимым, указанным в приведенных ниже фрагментах кода:


Затем импортируйте эти два компонента в App.js
:

Ознакомившись с основами, вы можете начать создавать свое первое приложение на React.
Читайте также:
- React: основные ошибки мидл-разработчиков
- Как начать работать программистом почти без опыта
- React hooks: никакой магии, только массивы
Читайте нас в Telegram, VK и Дзен
Перевод статьи Muhammad Yahya: React Todo App Tutorial