Валидация в режиме onSubmit в связке
React Hook Form и YupResolver представляет
собой стратегию, при которой проверка данных выполняется строго в момент
отправки формы. Такой подход минимизирует количество вычислений во время
ввода и переносит всю нагрузку на финальный этап жизненного цикла
формы.
В основе лежит идея разделения ответственности: пользователь вводит
данные без немедленной валидации, а схема Yup применяется
только при попытке отправки.
YupResolver выступает адаптером между схемой валидации
Yup и системой управления формами
React Hook Form.
Основная задача заключается в преобразовании результатов схемы в
формат ошибок, который понимает React Hook Form.
При использовании режима onSubmit:
resolver активируется только при вызове
handleSubmit;Режим задаётся через параметр mode при инициализации
useForm.
import { useForm } from "react-hook-form";
import { yupResolver } from "@hookform/resolvers/yup";
import * as yup from "yup";
const schema = yup.object({
email: yup.string().email("Некорректный email").required("Обязательное поле"),
password: yup.string().min(6, "Минимум 6 символов").required("Обязательное поле"),
});
const form = useForm({
resolver: yupResolver(schema),
mode: "onSubmit",
});
В данном контексте mode: "onSubmit" означает, что
валидация не выполняется до момента вызова
handleSubmit.
Функция handleSubmit становится центральным узлом
процесса.
const onSub mit = (data) => {
console.log("валидные данные:", data);
};
<form onSub mit={form.handleSubmit(onSubmit)}>
<input {...form.register("email")} />
<input {...form.register("password")} />
<button type="submit">Отправить</button>
</form>
При вызове:
resolver;Yup выполняет синхронную или асинхронную
проверку;onSubmit.Ошибки, возвращаемые YupResolver, приводятся к
стандартной форме React Hook Form:
{
email: {
type: "validation",
message: "Некорректный email"
},
password: {
type: "min",
message: "Минимум 6 символов"
}
}
Каждое поле получает собственный объект ошибки, что позволяет выполнять точечное отображение состояния в UI.
Yup поддерживает асинхронные проверки, что влияет на
поведение onSubmit.
Типичный сценарий включает проверку уникальности данных:
const schema = yup.object({
username: yup
.string()
.test(
"check-username",
"Имя уже занято",
async (value) => {
const res = await fetch(`/api/check?username=${value}`);
const data = await res.json();
return data.available;
}
),
});
В режиме onSubmit асинхронная логика выполняется один
раз при отправке формы, что предотвращает множественные сетевые запросы
во время ввода.
Процесс обработки формы можно разложить на последовательность:
Пользователь инициирует submit
handleSubmit блокирует стандартное поведение
формы
resolver(yupSchema) получает все значения
формы
Yup выполняет валидацию всей структуры
Результат преобразуется в:
values (при успехе)errors (при ошибках)React Hook Form обновляет состояние
При отсутствии ошибок вызывается callback
onSubmit
При наличии ошибок выполнение onSubmit блокируется
полностью.
const onSub mit = (data) => {
// не выполнится при наличии ошибок
};
Форма остаётся в состоянии isSubmitting: false, но
заполняется объект errors, который хранится в
formState.
Режим onSubmit считается наиболее экономичным с точки
зрения вычислений.
Причины:
YupResolver;Однако при сложных схемах Yup с глубокими объектами
возможно увеличение времени обработки на этапе отправки.
YupResolver корректно обрабатывает вложенные
структуры:
const schema = yup.object({
user: yup.object({
name: yup.string().required(),
address: yup.object({
city: yup.string().required(),
}),
}),
});
Ошибки возвращаются с сохранением структуры пути:
{
user: {
address: {
city: {
message: "Обязательное поле"
}
}
}
}
При работе с массивами Yup сохраняет индексную адресацию
ошибок:
const schema = yup.object({
tags: yup.array().of(
yup.string().required("Пустое значение")
),
});
Результат ошибок:
{
tags: {
1: {
message: "Пустое значение"
}
}
}
После выполнения resolver обновляются ключевые
состояния:
errorsisValidisSubmittingtouchedFieldsВ режиме onSubmit часть этих состояний активируется
только после первой попытки отправки формы.
Несмотря на возможность асинхронных тестов в Yup, сам
процесс handleSubmit остаётся синхронным с точки зрения
потока управления: асинхронность инкапсулируется внутри
resolver.
Это означает, что:
isSubmitting;