React: интересная схема работы с формами
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
Результат:
Кроме названных выше полей, форма содержит кнопки для отправки формы («Создать аккаунт») и очистки всех полей («Очистить поля»). Она выглядит прилично (по крайней мере, на мой «вкус и цвет»