Доброго времени суток, друзья. В данной статье мы напишем свой список задач, используя React хуки. Данная статья будет интересна в первую очередь начинающим Frontend разработчикам и всем тем, кто хочет просто написать свое первое приложение на React. Для создания первоначального шаблона для разработки порекомендую вам использовать create-react-app либо react-cli-ui. Давайте приступим к самой разработке.
Видео тут:
Структура Todo
Для начала подготовим структуру нашего приложения, оно будет состоять из следующих файлов.- App.js
— ToDo.js
— ToDoForm.js
— index.css
— index.js
В index.js находится инициализация приложения путем добавления App компонента в div с айди #root. В самом App.js будет существовать наш список с элементами (Todo.js) с формой для ввода новых данных (ToDOForm.js) и файлом index.css, где будут храниться все стили приложения.
Давайте опишем структуру приложения в App.js
Пример (App.js):
import React, { useState } from "react";
//components
import ToDo from "./ToDo";
import ToDoForm from "./ToDoForm";
function App() {
const [todos, setTodos] = useState([]);
const addTask = (userInput) => {
};
const removeTask = (id) => {
};
const handleToggle = (id) => {
};
return (
<div className="App">
<header>
<h1>Список задач: {todos.length}</h1>
</header>
<ToDoForm addTask={addTask} />
{todos.map((todo) => {
return (
<ToDo
todo={todo}
key={todo.id}
toggleTask={handleToggle}
removeTask={removeTask}
/>
);
})}
</div>
);
}
export default App;
Компонент хранит в себе состояние задач в виде массива в useState. Имеются три функции для взаимодействия с интерфейсом.
addTask добавление новой задачи
removeTask удаление задачи
handleToggle переключение задачи с активной на выполненную
Сам компонент возвращает div, в котором имеется заголовок. Для большей наглядности в нем выводится количество элементов текущего списка.
Ниже находится компонент формы (ToDoForm), в которую передаётся функция addTask. И под ним выводится список текущих задач, который благодаря функции map выводит содержимое массива todos, элементами которого является компонент ToDo. В этот компонент передаётся текущий элемент массива todo, указывается key (по базовым правилам работы виртуального дома в React) и функции handleToggle и removeTask, которые были описаны выше. Давайте теперь подробно рассмотрим компонент формы (ToDoForm), в котором будет происходить все основное взаимодействие интерфейса с пользователем.
Форма добавления новой задачи
Пример:
import React, { useState } from "react";
const ToDoForm = ({ addTask }) => {
const [userInput, setUserInput] = useState("");
const handleChange = (e) => {
setUserInput(e.currentTarget.value);
};
const handleSubmit = (e) => {
e.preventDefault();
addTask(userInput);
setUserInput("");
};
const handleKeyPress = (e) => {
if (e.key === "Enter") {
handleSubmit(e);
}
};
return (
<form onSubmit={handleSubmit}>
<input
value={userInput}
type="text"
onChange={handleChange}
onKeyDown={handleKeyPress}
placeholder="Введите значение..."
/>
<button>Сохранить</button>
</form>
);
};
export default ToDoForm;
Посмотрим на компонент ToDoForm. Он состоит из состояния input, которое хранится в отельном useState. Функция handleChange для изменения значений инпута, handleSubmit для отправления значений в список задач и handleKeyPress для работы с кнопкой Enter, по клику на которую будет происходить вызов функции handleSubmit.
Сам компонент это просто форма с одним полем ввода и кнопкой «Сохранить».
Стоит обратить внимание на функцию handleSubmit, внутри которой мы передаем значение из поля ввода в функцию addTask, после чего вызываем функцию setUserInput с пустой строкой. Это нужно, чтобы поле ввода стало пустым сразу после отправления формы.
Элемент списка Todo
Последний из компонентов, который мы рассмотрим, является элемент списка задач.
Пример:
import React from "react";
const ToDo = ({ todo, toggleTask, removeTask }) => {
return (
<div key={todo.id + todo.key} className="item-todo">
<div
onClick={() => toggleTask(todo.id)}
className={todo.complete ? "item-text strike" : "item-text"}
>
{todo.task}
</div>
<div className="item-delete" onClick={() => removeTask(todo.id)}>
x
</div>
</div>
);
};
export default ToDo;
Как видите это просто div, внутри которого находятся еще два дива. В первом выводится значение самой задачи, а во втором находится крестик для ее удаления. По клику на название задачи происходит вызов функции toggleTask, в которую передается id задачи и в объекте поле complete меняет свое булевое значение (true/false) на противоположное, после чего меняются классы, и запись визуально становится неактивной (зачеркнута линией).
Давайте вернемся в App.js и посмотрим на реализацию функций, которые выполняют всю работу.
Дописываем функции в App
Пример:
import React, { useState } from "react";
//components
import ToDo from "./ToDo";
import ToDoForm from "./ToDoForm";
function App() {
const [todos, setTodos] = useState([]);
const addTask = (userInput) => {
if (userInput) {
const newItem = {
id: Math.random().toString(36).substr(2, 9),
task: userInput,
complete: false
};
setTodos([...todos, newItem]);
}
};
const removeTask = (id) => {
setTodos([...todos.filter((todo) => todo.id !== id)]);
};
const handleToggle = (id) => {
setTodos([
...todos.map((task) =>
task.id === id ? { ...task, complete: !task.complete } : { ...task }
)
]);
};
return (
<div className="App">
<header>
<h1>Список задач: {todos.length}</h1>
</header>
<ToDoForm addTask={addTask} />
{todos.map((todo) => {
return (
<ToDo
todo={todo}
key={todo.id}
toggleTask={handleToggle}
removeTask={removeTask}
/>
);
})}
</div>
);
}
export default App;
Как видите, в функции addTask используется спред оператор, в результате чего происходит добавление нового элемента с уникальным id, полем task и complete.
Функция removeTask принимает id, по которому фильтруется весь список задач и возвращается новое состояние списка в функцию setTodos.
В функции handleToggle так же принимается id задачи, по которому идет сравнение в массиве и изменение поля complete, если текущая выбранная id равна id из списка.
Немного стилей
И в завершение, чтобы наш список выглядел более привлекательнем, добавим немного CSS.
Пример:
.App {
text-align: center;
}
.App .item-todo {
padding: 14px;
width: 250px;
margin: 0 auto;
text-align: left;
margin-top: 15px;
background: linear-gradient(
90deg,
rgba(93, 12, 255, 1) 0%,
rgba(155, 0, 250, 1) 100%
);
color: #fff;
border: none;
border-radius: 5px;
cursor: pointer;
}
.App .item-todo .item-text {
display: inline-block;
cursor: pointer;
}
.App input {
padding: 14px 32px 14px 16px;
border-radius: 4px 0 0 4px;
border: 2px solid #5d0cff;
outline: none;
background: transparent;
}
.App button {
padding: 16px 7px;
border: none;
border-radius: 0 4px 4px 0;
cursor: pointer;
outline: none;
background: linear-gradient(
90deg,
rgba(93, 12, 255, 1) 0%,
rgba(155, 0, 250, 1) 100%
);
color: #fff;
text-transform: capitalize;
}
.App .item-todo .item-delete {
display: inline-block;
cursor: pointer;
float: right;
font-size: 22px;
position: relative;
left: -4px;
bottom: 5px;
}
.strike {
text-decoration: line-through;
}
Заключение
Сегодня мы написали свой список задач, используя современный подход в разработке React Hooks. Мы разобрали базовые кейсы взаимодействия пользователя с таким интерфейсом. Надеюсь, что данный материал был вам полезен. Учитесь, думайте, пишите код. Удачного кодинга, друзья!
Подписывайтесь на наш канал в Telegram и на YouTube для получения самой последней и актуальной информации.
Комментарии: