Пошук уроків, статей та іншого контенту
Освойте React Hook Form для реєстрації полів, керування станом, помилками й відправленням форми.
React Hook Form — бібліотека для роботи з формами в React. Вона спрощує:
реєстрацію полів;
збирання значень форми;
валідацію;
відображення помилок;
обробку відправлення;
відстеження стану форми.
На відміну від підходу з окремим useState для кожного поля, React Hook Form зазвичай використовує неконтрольовані поля. Це зменшує кількість оновлень компонента під час введення тексту.
Встановіть пакет у проєкті:
npm install react-hook-formОсновний хук бібліотеки — useForm:
import { useForm } from "react-hook-form";Виклик useForm() повертає методи й об’єкти для роботи з формою:
const {
register,
handleSubmit,
formState: { errors },
} = useForm();useFormregister — підключає поле до React Hook Form;
handleSubmit — перевіряє форму та викликає обробник;
formState.errors — містить помилки валідації;
formState.isSubmitting — показує, чи триває відправлення;
reset — очищає форму або встановлює нові значення;
watch — дає змогу отримати поточне значення поля.
Щоб підключити HTML-поле до React Hook Form, передайте йому результат виклику register:
<input {...register("email")} />Рядок "email" — це ім’я поля. Саме за цим ім’ям значення буде доступне в об’єкті даних форми.
Наприклад:
<input {...register("firstName")} />
<input {...register("lastName")} />Після відправлення форми дані матимуть такий вигляд:
{
firstName: "Олена",
lastName: "Коваль"
}Важливо не забувати оператор розгортання .... Він передає полю необхідні властивості та обробники подій.
Правила валідації передаються другим аргументом register:
<input
{...register("email", {
required: "Введіть електронну пошту",
pattern: {
value: /^[^\s@]+@[^\s@]+\.[^\s@]+$/,
message: "Введіть коректну електронну пошту",
},
})}
/>Поширені правила:
required — обов’язкове поле;
minLength — мінімальна довжина;
maxLength — максимальна довжина;
min — мінімальне числове значення;
max — максимальне числове значення;
pattern — перевірка за регулярним виразом;
validate — власна функція валідації.
Для правила можна передати як true, так і текст помилки:
<input
{...register("password", {
required: "Введіть пароль",
minLength: {
value: 8,
message: "Пароль має містити щонайменше 8 символів",
},
})}
/>Помилки доступні через formState.errors. Якщо поле не пройшло валідацію, у відповідному ключі з’явиться об’єкт із властивістю message.
{errors.email && <p>{errors.email.message}</p>}Безпечніший варіант — використовувати optional chaining:
{errors.email?.message && (
<p role="alert">{errors.email.message}</p>
)}Атрибут role="alert" повідомляє допоміжним технологіям, що текст є важливим повідомленням про помилку.
handleSubmit приймає функцію, яка буде викликана лише після успішної валідації:
const onSubmit = (data) => {
console.log(data);
};
<form onSubmit={handleSubmit(onSubmit)}>
{/* поля форми */}
</form>Якщо валідація не пройдена, onSubmit не виконається, а помилки з’являться в formState.errors.
Можна також передати окремий обробник для невалідної форми:
const onInvalid = (errors) => {
console.log("Форма містить помилки", errors);
};
<form onSubmit={handleSubmit(onSubmit, onInvalid)}>
{/* поля форми */}
</form>Нижче наведено компонент із такими можливостями:
реєстрація імені, email та пароля;
валідація обов’язкових полів;
перевірка формату email;
перевірка довжини пароля;
порівняння пароля з підтвердженням;
відображення помилок;
стан відправлення;
очищення форми після успішного надсилання.
import { useForm } from "react-hook-form";
export default function RegistrationForm() {
const {
register,
handleSubmit,
reset,
formState: { errors, isSubmitting, isSubmitSuccessful },
} = useForm({
mode: "onBlur",
defaultValues: {
name: "",
email: "",
password: "",
confirmPassword: "",
},
});
const onSubmit = async (data) => {
// Імітуємо запит до сервера
await new Promise((resolve) => {
setTimeout(resolve, 1000);
});
console.log("Дані реєстрації:", data);
reset();
};
return (
<form onSubmit={handleSubmit(onSubmit)} noValidate>
<div>
<label htmlFor="name">Ім’я</label>
<input
id="name"
type="text"
{...register("name", {
required: "Введіть ім’я",
minLength: {
value: 2,
message: "Ім’я має містити щонайменше 2 символи",
},
})}
/>
{errors.name?.message && (
<p role="alert">{errors.name.message}</p>
)}
</div>
<div>
<label htmlFor="email">Електронна пошта</label>
<input
id="email"
type="email"
{...register("email", {
required: "Введіть електронну пошту",
pattern: {
value: /^[^\s@]+@[^\s@]+\.[^\s@]+$/,
message: "Введіть коректну електронну пошту",
},
})}
/>
{errors.email?.message && (
<p role="alert">{errors.email.message}</p>
)}
</div>
<div>
<label htmlFor="password">Пароль</label>
<input
id="password"
type="password"
{...register("password", {
required: "Введіть пароль",
minLength: {
value: 8,
message: "Пароль має містити щонайменше 8 символів",
},
})}
/>
{errors.password?.message && (
<p role="alert">{errors.password.message}</p>
)}
</div>
<div>
<label htmlFor="confirmPassword">Підтвердження пароля</label>
<input
id="confirmPassword"
type="password"
{...register("confirmPassword", {
required: "Підтвердіть пароль",
validate: (value, formValues) =>
value === formValues.password || "Паролі не збігаються",
})}
/>
{errors.confirmPassword?.message && (
<p role="alert">{errors.confirmPassword.message}</p>
)}
</div>
<button type="submit" disabled={isSubmitting}>
{isSubmitting ? "Реєстрація..." : "Зареєструватися"}
</button>
{isSubmitSuccessful && (
<p role="status">Форму успішно надіслано</p>
)}
</form>
);
}mode: "onBlur" означає, що валідація запускається, коли користувач залишає поле. Інші поширені режими:
"onSubmit" — валідація під час відправлення, це режим за замовчуванням;
"onChange" — валідація після зміни значення;
"all" — валідація під час зміни та після втрати фокуса.
defaultValues задає початкові значення полів. Це зручно, коли потрібно заповнити форму початковими даними або явно визначити порожні значення.
isSubmitting стає true, поки асинхронна функція onSubmit не завершиться. На цей час кнопку можна заблокувати, щоб користувач не надіслав форму повторно.
reset() повертає поля до початкових значень. Якщо defaultValues містили порожні рядки, форма очиститься.
validateДля складніших правил використовуйте функцію validate. Вона має повернути:
true, якщо значення коректне;
рядок із повідомленням, якщо значення некоректне.
<input
{...register("username", {
validate: (value) => {
if (value.includes(" ")) {
return "Ім’я користувача не може містити пробілів";
}
return true;
},
})}
/>Функція validate також може отримати всі значення форми другим аргументом:
<input
{...register("confirmPassword", {
validate: (value, values) =>
value === values.password || "Паролі не збігаються",
})}
/>Це дає змогу перевіряти поле залежно від значення іншого поля.
Початкові значення задають під час виклику useForm:
const { register, reset } = useForm({
defaultValues: {
city: "Львів",
country: "Україна",
},
});Скинути форму до початкових значень можна так:
reset();Встановити інші значення для всієї форми:
reset({
city: "Київ",
country: "Україна",
});reset часто використовують після успішного надсилання або під час завантаження даних для редагування.
registerПоле без register не буде зареєстроване:
<input type="text" />Правильно:
<input type="text" {...register("name")} />handleSubmitНе слід передавати обробник напряму:
<form onSubmit={onSubmit}>У такому разі дані не пройдуть через валідацію React Hook Form.
Правильно:
<form onSubmit={handleSubmit(onSubmit)}>Помилка не є рядком безпосередньо:
<p>{errors.email}</p>Використовуйте її повідомлення:
<p>{errors.email?.message}</p>type у кнопкиУсередині форми кнопка за замовчуванням може поводитися як кнопка відправлення. Для явності вказуйте тип:
<button type="submit">Надіслати</button>Для кнопки очищення форми:
<button type="button" onClick={() => reset()}>
Очистити
</button>value без контролювання поляЯкщо поле має value, але його значення не оновлюється через onChange, воно може стати фактично незмінним. Для звичайних текстових полів не додавайте value без потреби — використовуйте defaultValues.
useForm створює контекст керування формою.
register підключає HTML-поля до React Hook Form.
handleSubmit запускає валідацію перед викликом обробника.
formState.errors містить помилки окремих полів.
Правила валідації передаються другим аргументом register.
validate дає змогу створювати власні перевірки.
isSubmitting допомагає керувати станом асинхронного надсилання.
defaultValues задає початкові значення.
reset очищає форму або встановлює нові значення.