Учебник о том, как создать многоэтапную форму с помощью React Hook Form.

Обновленная версия сообщения доступна на claritydev.net.

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

В этом посте мы создадим базовую многоступенчатую регистрационную форму, которая собирает информацию о пользователе, а затем представляет ее в виде подтверждения, которое можно просмотреть и отредактировать перед отправкой. Следует отметить, что форма значительно упрощена и, вероятно, будет иметь больше полей в реальном приложении, однако мы сохраним ее простоту, чтобы ее было легче понять. Кроме того, основное внимание уделяется части JS, и правильное оформление формы выходит за рамки этого руководства. Окончательная форма выглядит так (также доступна CodeSandbox):

Выбор структуры формы

Одной из самых сложных и важных вещей при работе с многошаговыми формами является определение их структуры. В конечном итоге выбор зависит от требований проекта и от того, что именно должна делать форма. Первый вариант часто заключается в использовании одного компонента формы, внутри которого рендерится активный шаг. В этом уроке мы будем использовать другой подход — каждый компонент шага будет отдельной формой, собирающей данные из своих полей и отправляющей их в центральное хранилище при отправке. Таким образом, мы достигаем четкого разделения задач, что упрощает адаптацию к будущим изменениям требований. Для логики формы будем использовать React Hook Form, что упрощает работу с формами. Для центрального хранилища мы будем использовать Контекст React, хотя для более сложных случаев лучше подойдет отдельная библиотека управления состоянием (например, Redux). Наконец, у каждого шага формы будет свой собственный маршрут, для которого мы будем использовать React Router.

Подводя итог, поток приложения таков:

  • Каждый шаг — это отдельная форма со своими обработчиками и локальным состоянием.
  • Нажатие Next отправляет данные с текущего шага в централизованное хранилище и перенаправляет на маршрут для следующего шага.
  • На последнем шаге отображаются все данные, и пользователи могут редактировать любой из шагов перед отправкой.

Настройка

Как упоминалось ранее, мы используем Context для сохранения состояния между шагами, а затем показываем данные формы в предварительном просмотре перед отправкой. Мы абстрагируем поставщиков и потребителей контекста в отдельный файл для упрощения использования.

Здесь мы создаем AppProvider, который обрабатывает состояние приложения и связанную с ним логику, и пользовательский хук useAppState. С этой абстракцией нам не нужно импортировать AppStateContext в каждый компонент. Кроме того, мы можем проверить, что компонент, вызывающий этот хук, используется внутри AppProvider.

Далее мы добавляем маршруты в приложение и создаем компоненты для шагов формы, оборачивая все это в файл AppProvider.

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

Этот компонент также обрабатывает сообщение об ошибке и, в качестве бонуса, устанавливает атрибут метки htmlFor в соответствии с идентификатором дочернего ввода, делая ввод правильно доступным. Нам просто нужно убедиться, что у ввода есть идентификатор. Мы также абстрагируем логику для компонентов Form, Input и Button, хотя они являются просто оболочками для нативных элементов HTML с применением пользовательского стиля.

Теперь мы можем начать создавать фактические компоненты для каждого шага. Они нарочито простые, иначе легко запутаться во всех деталях и крайних случаях. Форма будет состоять из 4 шагов:

  1. Контакты — получите основные данные пользователя — имя, адрес электронной почты и пароль.
  2. Образование — давайте представим, что наша форма используется на каком-то веб-сайте, посвященном образованию или карьере, и мы хотели бы узнать подробности об образовании пользователя.
  3. О себе — шаг со свободным текстовым полем, где пользователи могут предоставить более подробную информацию о себе.
  4. Подтвердить — этот шаг используется не для ввода реквизитов, а для их предварительного просмотра и редактирования при необходимости.

Кроме того, все поля на первом этапе будут обязательными и будут иметь базовую проверку, чтобы показать, как это обычно делается в форме React Hook.

React Hook Form внутренне обрабатывает состояние формы, поэтому все, что нам нужно сделать, это сохранить его в состояние нашего приложения после его проверки.

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

Мы могли бы пойти дальше с абстракциями и собрать данные для отображения в отдельную структуру, которую затем перебрать и отобразить. Однако такая СУХАЯ работа с кодом может оказаться проблематичной, когда мы получим новые требования, к которым код недостаточно надежен, чтобы адаптироваться. Одно важное правило, о котором следует помнить, заключается в том, что высушить код намного проще, чем отменить его.

Добавление индикатора шага

Форма, хотя и скудно оформленная, функциональна, что мы можем подтвердить, заполнив все данные и отправив их. В настоящее время пользователи не имеют четкого представления о том, сколько всего шагов и на каком этапе процесса они сейчас находятся. Это не очень хороший UX и делает многошаговые формы более пугающими, чем они есть на самом деле. Мы исправим это, добавив индикатор шага, также известный как степпер. Компонент Stepper в основном представляет собой навигацию для формы, но с отключенными ссылками:

Теперь мы можем добавить этот компонент в приложение:

С этим изменением у нас появилась полностью рабочая многошаговая форма с индикатором прогресса.

Пути улучшения

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

  • Индикатор шага немного улучшает UX, однако, когда пользователь возвращается к шагу, чтобы отредактировать его, ему нужно нажимать Next, пока не будет достигнут последний шаг. Это довольно раздражает, особенно при переходе к первому шагу. Чтобы помочь с этим, мы можем включить навигацию через степпер.
  • Если мы включим навигацию с помощью степпера, мы также рассмотрим сохранение состояния формы при навигации с помощью степпера, чтобы убедиться, что проверка поля не будет пропущена.
  • В качестве альтернативы мы могли бы отключить проверку обязательных полей формы и отображать статус каждого шага (если какие-либо необходимые данные отсутствуют) в степпере. Это полезно, когда мы разрешаем сохранять частичные данные как черновик.
  • В настоящее время, если пользователь вводит некоторые данные и решает выйти из формы, он теряет весь прогресс. Это становится проблемой, когда такая навигация выполняется по ошибке. В этом случае мы могли бы добавить подсказку, которая попросит пользователя подтвердить, хочет ли он перейти на другую страницу и потерять весь свой прогресс.

Первые два улучшения и их реализация обсуждаются в следующем посте.

Тестирование формы

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

Первоначально опубликовано на https://claritydev.net.

Дополнительные материалы на PlainEnglish.io. Подпишитесь на нашу бесплатную еженедельную рассылку новостей. Подпишитесь на нас в Twitter, LinkedIn, YouTube и Discord . Заинтересованы в хакинге роста? Ознакомьтесь с разделом Схема.