Учебное пособие по React Hooks: создайте список дел с помощью React Hooks

Учебное пособие по React Hooks Изучение

С выпуском React 16.8 в 2019 году React Hooks наконец-то стали доступны для использования в наших производственных приложениях. Это позволяет разработчикам React делать функциональные компоненты с отслеживанием состояния. Вместо использования компонента класса для хранения логики с отслеживанием состояния мы можем использовать функциональные компоненты.

React Hooks — мощный инструмент, поэтому, чтобы вы начали, сегодня мы составим список дел с помощью этого современного инструмента. К концу у вас будет первое приложение React с хуками!

Обзор Hooks React

В React перехватчики — это функции, которые позволяют подключаться к функциям состояния и жизненного цикла React из функциональных компонентов. Это позволяет использовать React без классов.

Когда вы впервые взглянете на документацию по React Hooks, вы увидите, что есть несколько хуков, которые мы можем использовать для наших приложений. Вы даже можете создать свой собственный. Некоторые из популярных включают:

  • useState: возвращает значение с сохранением состояния
  • useEffect: выполнять побочные эффекты от функциональных компонентов
  • useContext: принимает объекты контекста и возвращает текущее значение контекста
  • useCallback: передать встроенный обратный вызов и массив зависимостей

Некоторые преимущества крючков:

  • Изоляция логики с отслеживанием состояния, упрощающая тестирование
  • Совместное использование логики с отслеживанием состояния без реквизитов рендеринга или компонентов более высокого порядка
  • Разделение проблем вашего приложения на основе логики
  • Избегайте классов ES6

Единственный крючок, который нам понадобится для этого конкретного проекта списка дел, — это useState(). Этот хук заменяет потребность в объекте состояния в структуре компонента класса.

Читайте также:  Часто задаваемые вопросы React FAQ: настройка, установка, пользовательские события и рекомендации

При просмотре более старого унаследованного кода React, скорее всего, вы увидите что-то вроде следующего:

import React from ‘react’;
import ‘./App.css’;
class App extends React.Component {
 constructor(props) {
   super(props);
   this.state = {
     movies: [ «Star Wars», «Return of the Jedi», «Empire Strikes Back» ]
   }
 }
 render() {
   return (
     <div>
       {this.state.movies.map(movie => {
         return (
           <div key={movie}>
             {movie}
           </div>
         )
       })}
     </div>
   )
 }
}
export default App;

Структура компонента класса описывает экземпляр Appобъекта, состояние которого является массивом фильмов. Мы визуализируем этот массив фильмов, отображая объект состояния и возвращая по одному фильму для каждого из них в массиве.

Функциональные компоненты с отслеживанием состояния очень похожи в том, что они хранят состояние, но они намного проще. Возьмите следующее:

import React, { useState } from ‘react’;
import ‘./App.css’;
function App() {
 const initialValue = [
   «Star Wars», «Return of the Jedi», «Empire Strikes Back»,
 ]
 const [ movies, setMovies ] = useState(initialValue);
 return (
   <div>
     {movies.map((movie) => {
       return <div key={movie}>{movie}</div>;
     })}
   </div>
 );
}
export default App;

useState Крючок деконструкции в массив с двумя элементами в нем:

  • Переменная, которая держит наше государство ( movies)
  • Метод, который используется для обновления состояния, что, если вам нужно ( setMovies)

Теперь, когда у вас есть основная идея useStateReact Hook, давайте реализуем ее при создании приложения To Do List!

Список дел: приглашение к проекту

Наша цель — создать пользовательский интерфейс списка дел. Этот пользовательский интерфейс будет состоять из трех основных компонентов:

  • Заголовок, обозначающий список дел. Это просто базовый идентификатор приложения
  • Список для отображения каждого сделать пункт.
  • Форма, которая добавляет элемент задачи, чтобы сделать список. По умолчанию для завершения должно быть установлено значение false.

В нашем списке есть две дополнительные возможности, которые нам нужно создать:

  • Дайте возможность включать и выключать зачеркивание, обозначающее завершение.
  • Внизу списка будет компонент, который предложит пользователю удалить выполненные задачи. Это может быть кнопка или другой призыв к действию.

Пример приложения To Do List

Пример приложения To Do List

Пошаговое руководство по созданию списка дел

1. Создайте приложение React

  • пряжа: yarn create react-app todo-list
  • npm: npx create-react-app todo-list

cdв список задач и запустить yarn start(при использовании Yarn) ИЛИ npm start(при использовании npm). Теперь ваш проект должен быть запущен localhost:3000.

2. App.js

Найдите App.jsи избавьтесь от всего, что находится между двумя

тегами. Нам не понадобится какой-либо предварительно заполненный код. На данный момент у нас App.jsдовольно голые кости:

import React from ‘react’;
import ‘./App.css’;
function App() {
 return (
   <div className=»App»>
      Hello World! A To Do List Will Go here!
   </div>
 );
}
export default App;

Если вы хотите добавить строку или что-то еще, чтобы убедиться, что ваш экземпляр React работает на localhost, не стесняйтесь делать это.

3. Заголовок

Создайте новый файл в srcкаталоге и назовите его Header.js. Затем создайте презентационный компонент, который будет отображать заголовок, идентифицирующий имя вашего приложения. Экспортируйте свой заголовок и импортируйте его в App.js.  В пустом <div>добавьте <Header />.

Вот наш код на данный момент:

Header.js

import React from ‘react’;
const Header = () => {
   return (
       <header>
           <h1>To Do List</h1>
       </header>
   );
};
export default Header;

App.js

import React from ‘react’;
//components
import Header from «./Header»;
import ‘./App.css’;
function App() {
 return (
   <div className=»App»>
     <Header />
   </div>
 );
}
export default App;

Наш результат на данном этапе

Наш результат на данном этапе

4. Создайте фиктивные данные для тестирования приложения.

Скопируйте и вставьте этот объект JSON в новый файл в srcкаталоге с именем data.json. Мы собираемся работать с этими данными в нашем проекте, чтобы проверить, правильно ли все работает.

В App.js, добавьте import data from «./data.json«;в свой список импорта вверху страницы.

[{
   «id»: 1,
   «task»: «Give dog a bath»,
   «complete»: true
 }, {
   «id»: 2,
   «task»: «Do laundry»,
   «complete»: true
 }, {
   «id»: 3,
   «task»: «Vacuum floor»,
   «complete»: false
 }, {
   «id»: 4,
   «task»: «Feed cat»,
   «complete»: true
 }, {
   «id»: 5,
   «task»: «Change light bulbs»,
   «complete»: false
 }, {
   «id»: 6,
   «task»: «Go to Store»,
   «complete»: true
 }, {
   «id»: 7,
   «task»: «Fill gas tank»,
   «complete»: true
 }, {
   «id»: 8,
   «task»: «Change linens»,
   «complete»: false
 }, {
   «id»: 9,
   «task»: «Rake leaves»,
   «complete»: true
 }, {
   «id»: 10,
   «task»: «Bake Cookies»,
   «complete»: false
 }, {
   «id»: 11,
   «task»: «Take nap»,
   «complete»: true
 }, {
   «id»: 12,
   «task»: «Read book»,
   «complete»: true
 }, {
   «id»: 13,
   «task»: «Exercise»,
   «complete»: false
 }, {
   «id»: 14,
   «task»: «Give dog a bath»,
   «complete»: false
 }, {
   «id»: 15,
   «task»: «Do laundry»,
   «complete»: false
 }, {
   «id»: 16,
   «task»: «Vacuum floor»,
   «complete»: false
 }, {
   «id»: 17,
   «task»: «Feed cat»,
   «complete»: true
 }, {
   «id»: 18,
   «task»: «Change light bulbs»,
   «complete»: false
 }, {
   «id»: 19,
   «task»: «Go to Store»,
   «complete»: false
 }, {
   «id»: 20,
   «task»: «Fill gas tank»,
   «complete»: false
 }]

5. Прочтите список задач и отобразите

Следующее, что нам нужно сделать, это проверить нашу способность читать набор тестовых данных. Давайте воспользуемся нашим useState()крючком, чтобы подключить какое-то локальное состояние в App.js.

Базовый синтаксис для useState()

const [ variable, setVariable ] = useState(<initState?>); 

Примечание: не забудьте import React, { useState } from ‘react’;вверху страницы.

import React, { useState } from ‘react’;
import data from «./data.json»;
//components
import Header from «./Header»;
import ‘./App.css’;
function App() {
  const [ toDoList, setToDoList ] = useState(data);
 return (
   <div className=»App»>
     <Header />
   </div>
 );
}
export default App;

в App.js

Теперь нам нужно сопоставить toDoListи создать отдельные компоненты задачи. Создайте два новых файла в srcкаталоге с именем ToDoList.jsи ToDo.js.

ToDoList.jsФайл является контейнером, который содержит все наши несделанные, и ToDo.jsэто один единственный ряд в нашей To Do List.

Не забудьте экспортировать ToDoListи импортировать в App.js. Кроме того, экспортируйте ToDoи импортируйте его в ToDoList.js. Он нам понадобится, когда мы вернем наши отдельные компоненты в нашу функцию карты.

import React, { useState } from ‘react’;
import data from «./data.json»;
//components
import Header from «./Header»;
import ToDoList from «./ToDoList»;
import ‘./App.css’;
function App() {
  const [ toDoList, setToDoList ] = useState(data);
 return (
   <div className=»App»>
     <Header />
     <ToDoList toDoList={toDoList}/>
   </div>
 );
}
export default App;

В App.js

Поскольку наша логика состояния удерживается App.js(скоро станет ясно, почему это так), нам нужно передать всю нашу логику toDoListнашему компоненту.

В нашем ToDoList мы сопоставим todoListобъект, который был передан в качестве реквизита, для создания отдельных задач. Не забудьте передать отдельные задачи в качестве опоры для компонента ToDo.

import React from ‘react’;
import ToDo from ‘./ToDo’;
const ToDoList = ({toDoList}) => {
   return (
       <div>
           {toDoList.map(todo => {
               return (
                   <ToDo todo={todo} />
               )
           })}
       </div>
   );
};
export default ToDoList;

В ToDoList.js

Все, что мы хотим от компонента ToDo, — это реальная задача, которая есть в нашем списке. Нам также нужно будет использовать completeсвойство объекта todo, чтобы указать, украшено ли что-либо зачеркиванием.

import React from ‘react’;
const ToDo = ({todo}) => {
   return (
       <div>
           {todo.task}
       </div>
   );
};
export default ToDo;

В ToDo.js

Однако на данный момент у вас должно быть что-то похожее на снимок экрана ниже. У нас есть заголовок с некоторыми задачами под ним!

Однако на данный момент у вас должно быть что-то похожее на снимок экрана ниже

6. Переключить завершение задачи

Давайте займемся включением и выключением независимо от того, выполнена ли задача.

Давайте сначала добавим classNameк нашему индивидуальному компоненту ToDo, который поможет нам со стилем. Мы собираемся использовать немного JavaScript, чтобы помочь нам здесь. Здесь мы добавляем атрибут classNameи устанавливаем его равным выражению JavaScript, которое задает вопрос, завершено ли задание.

Примечание: все, что находится между фигурными скобками, при использовании сигналов JSX, что мы используем JavaScript.

 const ToDo = ({todo}) => {
   return (
       <div className={todo.complete ? «strike» : «»}>
           {todo.task}
       </div>
   );
};

Если наша задача завершена, мы будем использовать className strikeдля обеспечения стиля. В противном случае не будет className. В нашем index.cssдобавляем следующее:

.strike {
   text-decoration: line-through;
}

Теперь, если вы взглянете на свое приложение React, вы должны увидеть некоторые задачи со сквозной линией, указывающей на то, что проект или задача выполнены.

Затем нам нужно создать функцию, которая будет переключать полное значение с true на false. Для этого нужно вернуться, App.jsпоскольку там находится наше государство.

Создать функцию переключения ( toggle()) довольно просто. Мы хотим, чтобы, когда пользователь нажимает на задачу, мы хотим изменить состояние завершения на true, если оно false, или наоборот. Для этого мы будем использовать вторую переменную в нашем деконструированном useStateмассиве.

 const handleToggle = (id) => {
   let mapped = toDoList.map(task => {
     return task.id == id ? { …task, complete: !task.complete } : { …task};
   });
   setToDoList(mapped);
 }

В App.js

Для этой функции я передал идентификатор элемента, который был нажат. Отображение поверх toDoListсоздает новый массив. Мы можем найти идентификатор текущей цели, а затем перевернуть задачу, чтобы она была завершена или не завершена, в зависимости от уже переданного логического значения.

setToDoList(mapped)аналогичен тому this.setState({ toDoList: mapped }), который использовался, когда мы работали с состоянием в компонентах класса.

Теперь вы можете включать и выключать завершенные задачи!

Удалить выполненные задачи

Что мы будем делать со всеми перечеркнутыми, выполненными задачами? Удалим их! Создайте кнопку, у которой будет onClickобработчик, который отфильтровывает все завершенные элементы.

Это очень похоже на handleToggleфункцию, которую мы только что сделали. Все, что нам нужно сделать, это взять toDoListи отфильтровать его, вернуть все незавершенные элементы, а затем установить отфильтрованный массив toDoList.

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

const handleFilter = () => {
   let filtered = toDoList.filter(task => {
     return !task.complete;
   });
   setToDoList(filtered);
 }

Затем добавьте кнопку в конец ToDoListкомпонента и установите onClickдля активации handleFilterфункции. Вы должны быть уверены, что добавляете свою handleFilterфункцию, App.jsа затем передаете ее в качестве реквизита в ToDoList.

import React from ‘react’;
import ToDo from ‘./ToDo’;
const ToDoList = ({toDoList, handleToggle, handleFilter}) => {
   return (
       <div>
           {toDoList.map(todo => {
               return (
                   <ToDo todo={todo} handleToggle={handleToggle} handleFilter={handleFilter}/>
               )
           })}
           <button style={{margin: ’20px’}} onClick={handleFilter}>Clear Completed</button>
       </div>
   );
};
export default ToDoList;

В ToDoList.js

8. Добавляйте задачи с помощью компонента формы.

Последний пункт в нашем списке — создание компонента формы, который будет обрабатывать добавление задач в наш ToDoList. Создайте новый файл в своем srcкаталоге и вызовите его ToDoForm.js.

Создайте базовую форму, которая позволит пользователю вводить имя задачи, нажимать ввод или нажимать кнопку, а также запускать функцию для добавления задачи. Чтобы форма работала правильно, мы должны отслеживать изменения по мере продвижения, поэтому логически мы должны обрабатывать то, что происходит при изменении ввода.

Логика формы

Чтобы наши формы работали, нам необходимы четыре основные вещи:

  • Локальное состояние (поэтому нам нужно будет задействовать useState()хук)
  • Наш компонент формы с входным значением, присвоенным правильной переменной
  • Функция, которая обрабатывает изменения состояния
  • Функция для обработки отправки формы

useState для обработки пользовательского ввода

Добавьте импорт для useStateловушки в свой импорт React. Наше состояние здесь будет отслеживать любой ввод, который пользователь вводит в свою форму. В качестве начального состояния устанавливается пустая строка, поскольку в форме еще ничего не должно быть.

const [ userInput, setUserInput ] = useState('');

Компонент формы

Теперь создайте компонент формы, который инкапсулирует ввод и кнопку. Довольно простой. Позже ты сможешь поиграть со стилем.

Input.value

Ваш <input>элемент должен иметь связанное с ним значение, которое соответствует имени вашей переменной состояния (я назвал свою userInput). Обработчик изменений будет принимать здесь значение и устанавливать состояние при каждом изменении.

<input value={userInput} type="text" onChange={handleChange} placeholder="Enter task..."/>

handleChange

Это функция, которая будет обрабатывать изменения локального состояния. Каждый раз, когда пользователь вводит текст в поле ввода, состояние будет меняться, отражая последний ввод.

const handleChange = (e) => {
       setUserInput(e.currentTarget.value)
   }

handleSubmit

Когда пользователь нажимает «Enter» или нажимает кнопку «Submit», эта функция запускается для добавления задачи в toDoListмассив.

const handleSubmit = (e) => {
       e.preventDefault();
       addTask(userInput);
       setUserInput(“”);
 
   }

Когда мы используем формы, не забывайте использовать, e.preventDefault()потому что мы не хотим, чтобы выполнялось действие по умолчанию. В этом случае он перезагрузит страницу, и все измененное вернется к исходному состоянию.

Не забудьте userInputвернуть пустую строку после выполнения addTaskфункции. Это вернет форму к пустому вводу.

addTask Далее идет функция addTask. Эта функция используется, App.jsпоскольку именно там находится все наше toDoListсостояние. Нам нужно иметь возможность установить новый массив в состояние using, setToDoListи мы можем сделать это только тогда, когда addTaskфункция имеет доступ к этому состоянию.

 const addTask = (userInput) => {
   let copy = [...toDoList];
   copy = [...copy, { id: toDoList.length + 1, task: userInput, complete: false }];
   setToDoList(copy);
 }

Эта функция принимает userInput, который мы собрали из состояния нашего компонента формы. Сделайте копию, toDoListчтобы мы напрямую не манипулировали состоянием.

Затем переназначьте копию новому массиву с расширением копии и новым элементом списка, отмеченным в конце. Это можно было бы записать по-другому:

copy.push({id: toDoList.length + 1, task: userInput, complete: false });

Убедитесь, что вы передаете addTaskподпорку ToDoForm.

Что учить дальше

Поздравляю! Теперь вы составили список дел, используя перехватчики React. Если вы обнаружили, что это довольно просто, немного поиграйте с кодом и попробуйте реализовать больше функций.

Вот несколько дополнительных вещей, которые вы можете сделать, чтобы дать вам некоторые идеи:

  • Добавьте возможность создавать срок выполнения для каждой задачи или рейтинг приоритета
  • Дайте возможность отсортировать список по сроку или приоритету
  • Создайте бэкэнд, чтобы ваш список дел сохранялся
  • Приложение стиля с использованием React-Bootstrap или CSS-in-JS
  • Используйте контекстный API, используя перехватчик useContext вместо локального состояния и свойств.
Оцените статью
bestprogrammer.ru
Добавить комментарий