Делаем CRUD приложение с помощью React-hooks

Создаем стандартное CRUD-приложение с помощью react-hooks.

(перевод-конспект статьи от Tania Rascia + текст/код от себя)

(первая часть «Знакомство с хуками» здесь)

делаем CRUD приложение react hooks заглавная картинка

Напомню про разницу между формой создания компонентов в react:

Как вы знаете многие фичи доступны лишь для класса, например — state и lifecycle-методы. Хуки добавляют эти возможности для stateless-компонентов (функциональных компонентов, компонентов созданных с помощью function).

В данном посте мы сделаем CRUD-приложение только на хуках без классов, чтобы научиться использовать react hooks. Мы будем использовать state хук и effect хук на функциональных компонентах.

Можно стартануть проект с помощью CRA или взять этот репозиторий за основу. Ветка — 1.prepair

В репозитории находятся стартовые файлы, среди которых:

src/App.js

первый скрин CRUD на react-hooks


Вспоминаем как работает useState хук

В первой части, мы уже разобрались с useState хуком.

Следовательно, глупый пример со счетчиком выглядит так:

Исходный код (ветка 2-count-example)


Настраиваем внешний вид

Добавим статичных данных в App и отрисуем табличку (UserTable) и форму добавления нового пользователя (AddUserForm).

src/tables/UserTable.js

src/forms/AddUserForm.js

src/App.js

таблица пользователей и форма добавления

Форма сейчас, разумеется не работает, о чем у нас есть предупреждение на скрине.

Добавление пользователя

Подытожим: у нас есть «статичные» данные, есть компонент добавления юзера. Что нам нужно?

  • научиться изменять usersData в компоненте App (usersTable сразу же перерисуется) как-нибудь;
  • научиться изменять usersData через компонент-форму (то есть, передать туда коллбэк-функцию, которую вызывать на submit, и изменять usersData в App);
  • научиться в AddUserForm работать с формой через хуки;

Начнем с первого пункта:

src/App.js

Теперь можем выполнить в консоли:

setUsers([{ id: 3, name: 'Link', username: 'thelegend' }])

set state в консоли

Функция изменения данных — работает. Теперь необходимо передать ее в AddUserForm, но при этом не перезатирать массив, а добавлять в него новые элементы. Так же, сразу заполним корректно значение параметра id.

Функцию передали, осталось вызывать ее на submit, но для начала наладим работу формы:

Форма работает, и теперь мы готовы добить submit:

таблица обновляется

В принципе, если вы знакомы с тем как работает передача props в реакте, вы должны уловить связь. Если нет — пишите вопросы в комментариях, разберемся.

Исходный код (ветка 3-add-user)


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

Порядок решения задачи:

  • написать функцию для удаления (разместить в App);
  • передать ее в качестве props в UserTable;
  • в UserTable «повесить» эту функцию на кнопку;

Удаление реализуем через filter

src/App.js

src/tables/UserTable.js

удаление пользователя react-hook


Обновление пользователя

Из статьи Tania:

Финальный кусочек пазла — это редактирование пользователя. Этого можно достичь так же, как и в случае с добавлением пользователя, однако нам нужно уметь идентифицировать какой пользователь в данный момент редактируется. В компонентах созданных с помощью class, мы могли сделать это в componentDidUpdate, но сейчас мы будем использовать Effect Hook. Effect hook — это как-будто скомбинированный componentDidMount и componentDidUpdate.

Таня, предлагает нам использовать новый компонент EditUserForm с подставленными туда name и username, в момент, когда будет нажата кнопка edit.

Так же нам придется добавить флаг «редактируется/не редактируется», какой пользователь сейчас на «редактировании» и начальное значение полей формы в App.

src/forms/EditUserForm.js

Добавим в App:

  • флаг editing;
  • информацию о том, какой пользователь сейчас редактируется (currentUser);
  • функцию editRow, которая будет вызываться по клику на кнопку Edit и будет подставлять пользователя в форму редактирования;
  • функцию updateUser, которая, непосредственно, будет обновлять пользователя;
  • развилку в render, чтобы показывать форму редактирования или форму добавления, в зависимости от editing;

src/App.js

src/tables/UserTable.js

(выше в руководстве был небольшой косяк — имена файлов компонентов в директориях начинались с маленькой буквы, исправлено в исходном коде ниже)

Исходный код на данный момент (ветка 5-edit-user)

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


Использование Effect Hook

Проблема на данный момент: если кликнуть сначала на редактирование одного пользователя, а потом на другого — то данные в форме не изменятся, хотя компонент получает props новые и перерисовывается как нужно. Для проверки, я добавил в шаблон props.currentUser.name рядом с Name

проблема редактирования пользователя

Логично, что у нас в state компонента (который сделан с помощью хука useState и функции обновления setUser) не приходят новые значения из props.

(для тех, кто работает с react давно, это может быть звоночком в сторону componentWillReceiveProps, а для тех, кто знаком позже — componentDidUpdate).

В чем суть проблемы: мы должны сказать компоненту, что если свойства (props) изменились, то нужно «обновить стейт«. То есть, мы должны каким-то образом в stateless-компоненте использовать componentDidUpdate метод. Здесь на помощь, приходит effect hook.

Бинго!


Осталось слегка подправить работу приложения. Сейчас, если удалить пользователя, который редактируется в данный момент, в форме останутся не актуальные данные. Чтобы ее очистить в момент удаления, достаточно обновить флаг editing в deleteUser:

Исходный код (ветка 6-complete)


Дополнительные материалы

Понравилась статья? Поделиться с друзьями:
Комментариев: 2
  1. Игоречег

    Очень хорошая статья.
    Единственный вопрос, который остался, как бы выглядела реализация компонента EditForm в качестве классового компонента? Точнее метод componentDidUpdate!

  2. Liza

    Спасибо Вам огромное! Очень помогло в понимании react))

Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: