React Hook Form
React Hook Form — популярная библиотека для форм. Меньше ререндеров, встроенная валидация, удобный API.
Установка
npm install react-hook-form
Базовый пример
import { useForm } from 'react-hook-form';
type FormValues = {
email: string;
password: string;
};
function LoginForm() {
const { register, handleSubmit, formState: { errors } } = useForm<FormValues>();
function onSubmit(data: FormValues) {
console.log(data);
}
return (
<form onSubmit={handleSubmit(onSubmit)}>
<input {...register('email')} />
{errors.email && <p>{errors.email.message}</p>}
<input type="password" {...register('password')} />
{errors.password && <p>{errors.password.message}</p>}
<button>Войти</button>
</form>
);
}
register регистрирует поле. handleSubmit оборачивает отправку. formState.errors содержит ошибки.
Валидация
<input
{...register('email', {
required: 'Email обязателен',
pattern: {
value: /^\S+@\S+\.\S+$/,
message: 'Некорректный email',
},
})}
/>
<input
type="password"
{...register('password', {
required: 'Пароль обязателен',
minLength: { value: 8, message: 'Минимум 8 символов' },
})}
/>
Правила:
requiredmin,maxminLength,maxLengthpatternvalidate— кастомная функция
Кастомная валидация
<input
{...register('username', {
validate: (value) =>
value !== 'admin' || 'Имя admin занято',
})}
/>
// Или функция
validate: (value) => {
if (value.length < 3) return 'Слишком короткое';
if (!/^[a-z]+$/.test(value)) return 'Только строчные буквы';
return true;
}
Значения по умолчанию
useForm<FormValues>({
defaultValues: {
email: '',
password: '',
},
});
Состояние формы
const {
formState: { errors, isSubmitting, isDirty, isValid },
} = useForm<FormValues>();
errors— объект ошибокisSubmitting— идёт отправкаisDirty— были измененияisValid— форма валидна
Сброс
const { reset } = useForm<FormValues>();
reset(); // к defaultValues
reset({ email: '' }); // к указанным
Watch
Следить за значением:
const { watch } = useForm<FormValues>();
const email = watch('email');
const allValues = watch();
SetValue и getValues
const { setValue, getValues } = useForm<FormValues>();
setValue('email', 'test@example.com');
const current = getValues('email');
Controller для сторонних компонентов
Если компонент не поддерживает ref (например, UI-библиотека):
import { Controller, useForm } from 'react-hook-form';
<Controller
name="birthday"
control={control}
render={({ field }) => (
<DatePicker {...field} />
)}
/>
Отправка на сервер
async function onSubmit(data: FormValues) {
const res = await fetch('/api/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data),
});
if (!res.ok) {
const errors = await res.json();
// setError('email', { message: errors.email });
}
}
Почему быстрее
React Hook Form использует неконтролируемые поля. Значения читаются при отправке, а не на каждый ввод. Это уменьшает количество ререндеров.
Итоги
- React Hook Form уменьшает ререндеры
register,handleSubmit,formState- Встроенная валидация
Controllerдля сторонних компонентовwatch,setValue,resetдля управления- Стандарт для сложных форм