Формы и глобальное состояние

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

Создание формы

Для инициализации формы используется компонент <Form> с ключевыми пропсами:

import { Form, Input, Button } from 'antd';

<Form
  name="basicForm"
  initialValues={{ username: '', password: '' }}
  onFin ish={onFinish}
  onFinishFai led={onFinishFailed}
>
  <Form.Item
    label="Имя пользователя"
    name="username"
    rules={[{ required: true, message: 'Введите имя пользователя!' }]}
  >
    <Input />
  </Form.Item>

  <Form.Item
    label="Пароль"
    name="password"
    rules={[{ required: true, message: 'Введите пароль!' }]}
  >
    <Input.Password />
  </Form.Item>

  <Form.Item>
    <Button type="primary" htmlType="submit">
      Войти
    </Button>
  </Form.Item>
</Form>
  • name — уникальный идентификатор формы, используемый для связывания с состоянием.
  • initialValues — объект с начальными значениями полей формы.
  • onFinish — вызывается при успешной валидации формы.
  • onFinishFailed — срабатывает, если валидация не прошла.

Валидация и правила

Компонент Form.Item позволяет задавать правила валидации через массив rules. Примеры правил:

  • required: true — обязательное поле.
  • type: 'email' — проверка формата email.
  • min и max — ограничения длины строки.
  • pattern — регулярное выражение для сложной проверки.
<Form.Item
  label="Email"
  name="email"
  rules={[
    { required: true, message: 'Введите email!' },
    { type: 'email', message: 'Неверный формат email!' }
  ]}
>
  <Input />
</Form.Item>

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

Form использует внутренний объект состояния, доступный через Form.useForm():

const [form] = Form.useForm();

const onRe set = () => {
  form.resetFields();
};

<Form form={form} name="controlForm">
  ...
</Form>
<Button onCl ick={onReset}>Сбросить</Button>
  • form.resetFields() — сброс всех полей к initialValues.
  • form.setFieldsValue({ key: value }) — программное изменение конкретного поля.
  • form.validateFields() — ручная проверка валидности формы.

Динамические формы

Ant Design поддерживает динамические поля, что полезно при работе с массивами данных:

<Form.List name="users">
  {(fields, { add, remove }) => (
    <>
      {fields.map(field => (
        <Form.Item {...field} key={field.key}>
          <Input placeholder="Имя пользователя" />
          <Button onCl ick={() => remove(field.name)}>Удалить</Button>
        </Form.Item>
      ))}
      <Button onCl ick={() => add()}>Добавить пользователя</Button>
    </>
  )}
</Form.List>

Form.List позволяет добавлять и удалять поля без потери состояния других элементов формы.


Интеграция с глобальным состоянием

В реальных приложениях формы часто должны синхронизироваться с глобальным состоянием, например, через Redux или Zustand.

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

import { useDispatch, useSelector } from 'react-redux';
import { updateUser } from './userSlice';

const dispatch = useDispatch();
const user = useSelector(state => state.user);

<Form
  form={form}
  initialValues={user}
  onFin ish={values => dispatch(updateUser(values))}
>
  ...
</Form>
  • initialValues берутся из глобального состояния.
  • Изменения формы отправляются через dispatch.

Двусторонняя синхронизация

Для полной синхронизации можно использовать form.setFieldsValue при изменении глобального состояния:

useEffect(() => {
  form.setFieldsValue(user);
}, [user]);

Это гарантирует, что изменения в глобальном состоянии сразу отразятся в форме, а пользовательский ввод обновит глобальный стор при onFinish.

Управление формой через контекст

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

<Form.Provider
  onFormFin ish={(name, { values, forms }) => {
    if (name === 'loginForm') {
      forms['profileForm'].setFieldsValue({ username: values.username });
    }
  }}
>
  <Form name="loginForm">...</Form>
  <Form name="profileForm">...</Form>
</Form.Provider>
  • onFormFinish реагирует на завершение любой формы в провайдере.
  • Можно синхронизировать поля между разными формами без внешнего глобального состояния.

Особенности производительности

  • Контролируемые и неконтролируемые поля: использование Form.Item делает поля контролируемыми, что облегчает валидацию, но увеличивает ререндеры при большом количестве элементов.
  • Memoization компонентов: для тяжелых форм рекомендуется использовать React.memo или useCallback для кнопок и динамических полей.
  • Отложенная валидация: параметр validateTrigger позволяет задавать момент проверки (onChange, onBlur), уменьшая лишние ререндеры.
<Form.Item
  name="username"
  rules={[{ required: true, message: 'Введите имя!' }]}
  validateTrigger="onBlur"
>
  <Input />
</Form.Item>

Продвинутые возможности

  • Кастомные валидаторы через validator:
rules={[
  {
    validator: (_, value) =>
      value.length >= 5 ? Promise.resolve() : Promise.reject('Минимум 5 символов')
  }
]}
  • Связывание полей с dependencies для условной валидации:
<Form.Item
  name="confirm"
  dependencies={['password']}
  rules={[
    ({ getFieldValue }) => ({
      validator(_, value) {
        if (!value || getFieldValue('password') === value) return Promise.resolve();
        return Promise.reject('Пароли не совпадают!');
      }
    })
  ]}
>
  <Input.Password />
</Form.Item>
  • Стилизация ошибок и динамических сообщений с использованием validateStatus и help:
<Form.Item
  validateStatus="error"
  help="Поле обязательно для заполнения"
>
  <Input />
</Form.Item>
  • Интеграция с серверной логикой через onFinish и form.validateFields позволяет обрабатывать асинхронные ошибки без потери UX.

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