Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти Інструменти Події
Інше
Про нас Реклама

Навіщо React Hook Form і Zod і як поєднати їх у формі?

Для простих форм вистачає нативних засобів React 19 (action, useActionState). Коли полів багато, є валідація з залежностями між полями, динамічні списки полів і складний UX помилок, - зручніше бібліотека.

React Hook Form керує формою через неконтрольовані поля й refs: введення не викликає рендер усієї форми. Стан помилок, «брудності», відправки - окремо.

Zod описує схему даних, з якої виходить і валідація, і тип TypeScript.

import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { z } from 'zod';

const schema = z.object({
  email: z.email('Некоректна адреса'),
  password: z.string().min(8, 'Щонайменше 8 символів'),
  age: z.coerce.number().int().min(18, 'Лише для повнолітніх'),
});

type FormValues = z.infer<typeof schema>;

function SignUpForm() {
  const {
    register,
    handleSubmit,
    formState: { errors, isSubmitting },
  } = useForm<FormValues>({ resolver: zodResolver(schema) });

  const onSubmit = async (values: FormValues) => {
    await api.signUp(values);
  };

  return (
    <form onSubmit={handleSubmit(onSubmit)} noValidate>
      <input type="email" {...register('email')} aria-invalid={!!errors.email} />
      {errors.email && <p role="alert">{errors.email.message}</p>}

      <input type="password" {...register('password')} />
      {errors.password && <p role="alert">{errors.password.message}</p>}

      <input type="number" {...register('age')} />

      <button disabled={isSubmitting}>Зареєструватися</button>
    </form>
  );
}

Що дає поєднання:

  • одна схема - і правила, і тип даних (z.infer); схему можна використати повторно на сервері (Node) чи для перевірки відповіді API;
  • handleSubmit викликає onSubmit лише з валідними даними, а при помилках ставить фокус на перше невалідне поле;
  • режими перевірки: mode: 'onSubmit' (за замовчуванням), 'onBlur', 'onChange', 'onTouched'.

Що варто знати:

  • у Zod 4 формати рядків стали окремими функціями: z.email() замість старого z.string().email() (той лишився, але застарів);
  • значення полів - рядки: для чисел - z.coerce.number() чи valueAsNumber у register;
  • клієнтська валідація - лише зручність. Сервер (Laravel Form Request) перевіряє все заново, а його помилки треба показати у формі через setError;
  • для сторонніх компонентів (селекти, редактори) - Controller з React Hook Form.

Докладніше в документації: React Hook Form: початок роботи

Схожі питання