React: интересная схема работы с формами

jchwst6a3nwlxlscnmuw5tdhmry.png


Hello, world!

В этой статье я хочу рассказать о схеме (назовем ее так) работы с формами в React, которая на сегодняшний день кажется мне наиболее эффективной. Эта схема предполагает использование React Hook Form для обработки форм и Zod для валидации пользовательских данных. Применение данной схемы имеет несколько существенных преимуществ по сравнению с использованием других решений или реализацией необходимого функционала вручную. Главными преимуществами являются минимизация количества шаблонного кода и автоматическое выведение типов (type inference).

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

Интересно? Тогда прошу под кат.

В качестве примера разработаем простую форму регистрации, содержащую следующие поля:


  • имя пользователя;
  • возраст;
  • адрес электронной почты;
  • пароль;
  • подтверждение пароля.

А также индикатор (чекбокс) принятия неких условий использования.

Все поля будут обязательными. О конкретных требованиях к каждому полю поговорим немного позднее.


Подготовка, настройка проекта и создание формы

Создаем шаблон проекта React с поддержкой TypeScript с помощью Vite (для работы с зависимостями я буду использовать Yarn):

# react-hook-form-zod - название проекта
# react-ts - используемый шаблон
yarn create vite react-hook-form-zod --template react-ts

Переходим в созданную директорию, устанавливаем зависимости и запускаем сервер для разработки:

cd react-hook-form-zod
yarn
yarn dev

Наша форма должна быть приятной глазу. Что бы нам использовать для ее стилизации? Как насчет Tailwind CSS? Устанавливаем эту библиотеку в качестве зависимости для разработки:

yarn add -D tailwindcss

Инициализируем ее:

npx tailwindcss init

Импортируем стили tailwind и определяем несколько переиспользуемых (reusable) стилей с помощью директивы @apply в файле src/index.css:

@tailwind base;
@tailwind components;
@tailwind utilities;

@layer components {
  .title {
    @apply text-2xl text-center font-bold leading-tight tracking-tight text-gray-900;
  }
  .label {
    @apply block mb-2 text-sm font-medium text-gray-900 cursor-pointer;
  }
  .input {
    @apply bg-gray-50 border-none outline outline-1 outline-gray-300 text-gray-900 rounded-md w-full p-2.5 focus-visible:outline-2 focus-visible:outline-blue-500 placeholder:text-sm aria-[invalid="true"]:outline-red-500 aria-[invalid="true"]:outline-2;
    transition: outline-color 150ms cubic-bezier(0.4, 0, 0.2, 1);
  }
  .error {
    @apply text-red-600 block text-sm absolute;
  }
  .btn {
    @apply text-white outline-none focus:ring-4 font-medium rounded-md text-sm px-5 py-2.5 text-center transition-colors disabled:opacity-50 disabled:cursor-not-allowed;
  }
  .btn-primary {
    @apply bg-primary-500 hover:bg-primary-700 focus:ring-primary-300 disabled:bg-primary-500;
  }
  .btn-error {
    @apply bg-red-500 hover:bg-red-700 focus:ring-red-300 disabled:bg-red-500;
  }
}

Определяем файлы для обработки и расширяем дефолтную цветовую схему tailwind в файле tailwind.config.cjs:

/** @type {import('tailwindcss').Config} */
module.exports = {
  content: ['./src/**/*.{js,jsx,ts,tsx}'],
  theme: {
    extend: {
      colors: {
        primary: {
          50: '#eff6ff',
          100: '#dbeafe',
          200: '#bfdbfe',
          300: '#93c5fd',
          400: '#60a5fa',
          500: '#3b82f6',
          600: '#2563eb',
          700: '#1d4ed8',
          800: '#1e40af',
          900: '#1e3a8a'
        }
      }
    }
  },
  plugins: []
}

Наконец, определяем форму в файле src/App.tsx:

function App() {
  return (
    

Создание аккаунта

) } export default App

Результат:


3211zil9jfkuwsk_88eygaahbkc.png

Кроме названных выше полей, форма содержит кнопки для отправки формы («Создать аккаунт») и очистки всех полей («Очистить поля»). Она выглядит прилично (по крайней мере, на мой «вкус и цвет»

© Habrahabr.ru