OnSubmit валидация

Валидация в режиме onSubmit в связке React Hook Form и YupResolver представляет собой стратегию, при которой проверка данных выполняется строго в момент отправки формы. Такой подход минимизирует количество вычислений во время ввода и переносит всю нагрузку на финальный этап жизненного цикла формы.

В основе лежит идея разделения ответственности: пользователь вводит данные без немедленной валидации, а схема Yup применяется только при попытке отправки.


Роль YupResolver в механизме onSubmit

YupResolver выступает адаптером между схемой валидации Yup и системой управления формами React Hook Form.

Основная задача заключается в преобразовании результатов схемы в формат ошибок, который понимает React Hook Form.

При использовании режима onSubmit:

  • ввод данных не вызывает валидацию на каждом изменении;
  • resolver активируется только при вызове handleSubmit;
  • результатом становится либо валидированный набор данных, либо структура ошибок.

Конфигурация режима onSubmit

Режим задаётся через параметр 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 при onSubmit

Функция 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>

При вызове:

  1. происходит запуск resolver;
  2. схема Yup выполняет синхронную или асинхронную проверку;
  3. формируется объект ошибок при наличии нарушений;
  4. при отсутствии ошибок вызывается onSubmit.

Структура ошибок в режиме onSubmit

Ошибки, возвращаемые YupResolver, приводятся к стандартной форме React Hook Form:

{
  email: {
    type: "validation",
    message: "Некорректный email"
  },
  password: {
    type: "min",
    message: "Минимум 6 символов"
  }
}

Каждое поле получает собственный объект ошибки, что позволяет выполнять точечное отображение состояния в UI.


Асинхронная валидация в YupResolver

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 асинхронная логика выполняется один раз при отправке формы, что предотвращает множественные сетевые запросы во время ввода.


Внутренний поток данных при onSubmit

Процесс обработки формы можно разложить на последовательность:

  1. Пользователь инициирует submit

  2. handleSubmit блокирует стандартное поведение формы

  3. resolver(yupSchema) получает все значения формы

  4. Yup выполняет валидацию всей структуры

  5. Результат преобразуется в:

    • values (при успехе)
    • errors (при ошибках)
  6. React Hook Form обновляет состояние

  7. При отсутствии ошибок вызывается callback onSubmit


Поведение при ошибках валидации

При наличии ошибок выполнение onSubmit блокируется полностью.

const onSub mit = (data) => {
  // не выполнится при наличии ошибок
};

Форма остаётся в состоянии isSubmitting: false, но заполняется объект errors, который хранится в formState.


Оптимизация производительности

Режим onSubmit считается наиболее экономичным с точки зрения вычислений.

Причины:

  • отсутствие постоянной валидации при вводе;
  • единичный вызов YupResolver;
  • минимизация количества пересчётов состояния формы.

Однако при сложных схемах Yup с глубокими объектами возможно увеличение времени обработки на этапе отправки.


Сравнение с другими режимами React Hook Form

onChange

  • валидация при каждом изменении поля;
  • высокая нагрузка при сложных схемах;
  • мгновенная обратная связь.

onBlur

  • валидация при потере фокуса;
  • баланс между производительностью и UX.

onSubmit

  • валидация только при отправке;
  • максимальная производительность во время ввода;
  • задержка обратной связи до момента submit.

Особенности работы с вложенными объектами

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: "Пустое значение"
    }
  }
}

Связь YupResolver и formState

После выполнения resolver обновляются ключевые состояния:

  • errors
  • isValid
  • isSubmitting
  • touchedFields

В режиме onSubmit часть этих состояний активируется только после первой попытки отправки формы.


Синхронная природа обработки onSubmit

Несмотря на возможность асинхронных тестов в Yup, сам процесс handleSubmit остаётся синхронным с точки зрения потока управления: асинхронность инкапсулируется внутри resolver.

Это означает, что:

  • UI блокируется только на время проверки;
  • повторные submit-запросы могут быть ограничены через isSubmitting;
  • обработка ошибок централизована в одном цикле валидации.