Работа с async-валидацией

В Ant Design (AntD) механизм валидации форм построен на использовании компонента Form и его поля Form.Item. Для асинхронной проверки данных применяется правило validator, которое позволяет интегрировать кастомную логику, включая обращения к серверу или к сторонним API.


Настройка асинхронного валидатора

validator — это функция, принимающая объект с параметрами { rule, value, callback } (в старых версиях) или современный синтаксис с использованием Promise:

const usernameValidator = async (_, value) => {
  if (!value) return Promise.reject(new Error("Поле обязательно"));
  
  const response = await fetch(`/api/check-username?username=${value}`);
  const data = await response.json();

  if (data.exists) {
    return Promise.reject(new Error("Имя пользователя занято"));
  }

  return Promise.resolve();
};

Ключевые моменты:

  • Функция должна возвращать Promise: resolve при успешной валидации, reject при ошибке.
  • value содержит текущее значение поля формы.
  • Асинхронная проверка позволяет динамически обращаться к серверу, например, для проверки уникальности email или имени пользователя.

Использование в Form.Item

Асинхронный валидатор подключается через поле rules:

<Form>
  <Form.Item
    label="Имя пользователя"
    name="username"
    rules={[
      { required: true, message: "Введите имя пользователя" },
      { validator: usernameValidator }
    ]}
  >
    <Input placeholder="Введите имя" />
  </Form.Item>
</Form>

Особенности:

  • rules может содержать несколько правил, в том числе синхронные и асинхронные.
  • Ошибка от асинхронного валидатора отображается так же, как стандартное сообщение message.
  • AntD автоматически управляет состоянием validating, позволяя показывать индикатор загрузки рядом с полем.

Поддержка нескольких асинхронных правил

Можно комбинировать несколько асинхронных проверок:

const emailValidator = async (_, value) => {
  const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
  if (!emailRegex.test(value)) {
    return Promise.reject(new Error("Некорректный email"));
  }

  const response = await fetch(`/api/check-email?email=${value}`);
  const data = await response.json();
  if (data.exists) {
    return Promise.reject(new Error("Email уже используется"));
  }

  return Promise.resolve();
};

<Form.Item
  label="Email"
  name="email"
  rules={[
    { required: true, message: "Введите email" },
    { validator: emailValidator }
  ]}
>
  <Input placeholder="Введите email" />
</Form.Item>

Особенности работы:

  • Асинхронные валидаторы выполняются последовательно в порядке перечисления в массиве rules.
  • Если одно правило вернёт reject, последующие правила не выполняются.
  • При большом количестве асинхронных проверок важно оптимизировать запросы к серверу, чтобы избежать лишних вызовов API при каждом вводе символа.

Управление состоянием validating

Компонент Form.Item автоматически выставляет флаг validating во время выполнения асинхронной проверки. Можно использовать это для отображения спиннера или подсказки пользователю:

<Form.Item
  label="Псевдоним"
  name="nickname"
  rules={[{ validator: nicknameValidator }]}
  hasFeedback
>
  <Input placeholder="Введите псевдоним" />
</Form.Item>
  • hasFeedback добавляет визуальный индикатор загрузки и статуса проверки.
  • Состояние validating доступно через форму, что позволяет реализовать кастомные UI-эффекты.

Советы по оптимизации

  1. Дебаунс запросов Использовать lodash.debounce или собственный механизм, чтобы не отправлять запрос на сервер при каждом вводе символа.

  2. Кеширование результатов Для полей с высокой вероятностью повторного ввода (например, username) можно хранить результаты предыдущих проверок.

  3. Обработка ошибок сети Асинхронный валидатор должен корректно обрабатывать сетевые ошибки и возвращать понятное сообщение:

const safeValidator = async (_, value) => {
  try {
    const response = await fetch(`/api/check?value=${value}`);
    const data = await response.json();
    if (!data.available) throw new Error("Значение уже занято");
  } catch (err) {
    return Promise.reject(new Error("Ошибка проверки на сервере"));
  }
};

Асинхронная валидация с кастомной кнопкой отправки

В Ant Design часто используется кнопка submit для запуска всех проверок:

<Form form={form} onFin ish={handleSubmit}>
  <Form.Item
    label="Логин"
    name="login"
    rules={[{ validator: loginValidator }]}
  >
    <Input />
  </Form.Item>

  <Form.Item>
    <Button type="primary" htmlType="submit">
      Зарегистрироваться
    </Button>
  </Form.Item>
</Form>
  • Асинхронные валидаторы автоматически выполняются при нажатии submit.
  • Если хотя бы один валидатор возвращает reject, событие onFinish не вызывается.
  • form.validateFields() можно использовать для программной проверки полей с асинхронной валидацией.

Интеграция с внешними библиотеками

Асинхронная валидация может быть совместима с:

  • Axios / Fetch для запросов к серверу.
  • Yup / Joi для сложной валидации схем, при этом AntD validator остаётся точкой интеграции.
  • React Query для кеширования и управления состоянием асинхронных проверок.

Резюме ключевых правил

  • Асинхронная валидация строится на validator с возвратом Promise.
  • Последовательность правил важна: при reject следующие правила не выполняются.
  • hasFeedback и validating позволяют отображать процесс проверки пользователю.
  • Оптимизация запросов и обработка ошибок сети повышают UX и производительность.

Асинхронная валидация в Ant Design делает формы гибкими, безопасными и готовыми для работы с серверной логикой, сохраняя привычный и удобный интерфейс для пользователей.