Связь формы с API

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

Создание формы и подключение обработчиков

Форма создается с использованием компонента Form, при этом каждый элемент управления (Input, Select, DatePicker и другие) оборачивается в Form.Item с указанием имени поля через name.

Пример базовой структуры формы:

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

const MyForm = () => {
  const [form] = Form.useForm();

  const handleSubmit = async (values) => {
    try {
      const response = await fetch('/api/submit', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(values),
      });
      const result = await response.json();
      console.log('Ответ сервера:', result);
    } catch (error) {
      console.error('Ошибка при отправке формы:', error);
    }
  };

  return (
    <Form form={form} onFin ish={handleSubmit} layout="vertical">
      <Form.Item
        label="Имя"
        name="username"
        rules={[{ required: true, message: 'Введите имя' }]}
      >
        <Input placeholder="Введите имя" />
      </Form.Item>
      <Form.Item
        label="Email"
        name="email"
        rules={[
          { required: true, message: 'Введите email' },
          { type: 'email', message: 'Некорректный email' },
        ]}
      >
        <Input placeholder="Введите email" />
      </Form.Item>
      <Form.Item>
        <Button type="primary" htmlType="submit">Отправить</Button>
      </Form.Item>
    </Form>
  );
};

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

  • form создается через Form.useForm() для управления состоянием формы программно.
  • onFinish вызывается после успешной валидации полей.
  • Form.Item с правилом required и типизацией type обеспечивает клиентскую валидацию перед отправкой.

Управление асинхронной отправкой и состояниями

При интеграции с API важно учитывать состояние запроса: загрузка, успешная отправка, ошибка. Для этого используют useState или сторонние библиотеки для управления состоянием (React Query, Redux Toolkit Query).

Пример с индикатором загрузки:

import { useState } from 'react';
import { Form, Input, Button, message } from 'antd';

const MyForm = () => {
  const [form] = Form.useForm();
  const [loading, setLoading] = useState(false);

  const handleSubmit = async (values) => {
    setLoading(true);
    try {
      const response = await fetch('/api/submit', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(values),
      });
      if (!response.ok) throw new Error('Сервер вернул ошибку');
      const result = await response.json();
      message.success('Форма успешно отправлена');
      form.resetFields();
    } catch (error) {
      message.error(`Ошибка: ${error.message}`);
    } finally {
      setLoading(false);
    }
  };

  return (
    <Form form={form} onFin ish={handleSubmit} layout="vertical">
      <Form.Item name="username" label="Имя" rules={[{ required: true }]}>
        <Input />
      </Form.Item>
      <Form.Item name="email" label="Email" rules={[{ required: true }, { type: 'email' }]}>
        <Input />
      </Form.Item>
      <Form.Item>
        <Button type="primary" htmlType="submit" loading={loading}>
          Отправить
        </Button>
      </Form.Item>
    </Form>
  );
};

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

  • loading свойство кнопки автоматически показывает индикатор ожидания.
  • Использование message позволяет быстро уведомлять пользователя о результате запроса.
  • form.resetFields() очищает форму после успешной отправки.

Предзаполнение формы данными из API

Для редактирования или просмотра существующих данных часто требуется загрузить их с сервера и отобразить в форме. В Ant Design используется метод form.setFieldsValue().

import { useEffect } from 'react';

useEffect(() => {
  const fetchData = async () => {
    const response = await fetch('/api/user/123');
    const data = await response.json();
    form.setFieldsValue({
      username: data.name,
      email: data.email,
    });
  };
  fetchData();
}, [form]);

Преимущества подхода:

  • Обеспечивает синхронизацию состояния формы с данными сервера.
  • Позволяет динамически менять значения полей после загрузки.

Обработка ошибок и валидация на стороне сервера

Ant Design позволяет вручную указывать ошибки для отдельных полей через метод form.setFields():

try {
  const response = await fetch('/api/submit', { ... });
  const result = await response.json();
  if (result.errors) {
    form.setFields([
      { name: 'username', errors: [result.errors.username] },
      { name: 'email', errors: [result.errors.email] },
    ]);
  }
} catch (error) {
  message.error('Ошибка сервера');
}

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

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

Использование Form.List для динамических наборов полей

Если API требует отправки массива объектов (например, список контактов), используется Form.List:

<Form.List name="contacts">
  {(fields, { add, remove }) => (
    <>
      {fields.map(field => (
        <Form.Item key={field.key}>
          <Form.Item {...field} name={[field.name, 'type']} noStyle>
            <Input placeholder="Тип контакта" />
          </Form.Item>
          <Form.Item {...field} name={[field.name, 'value']} noStyle>
            <Input placeholder="Значение" />
          </Form.Item>
          <Button onCl ick={() => remove(field.name)}>Удалить</Button>
        </Form.Item>
      ))}
      <Button onCl ick={() => add()}>Добавить контакт</Button>
    </>
  )}
</Form.List>

Преимущества:

  • Поля могут динамически добавляться и удаляться пользователем.
  • Данные формируются в структуру массива, готовую для отправки на сервер.

Интеграция с REST и GraphQL

Ant Design формы легко сочетаются с любым типом API. При работе с REST используется fetch или axios. Для GraphQL запросов можно комбинировать формы с apollo-client или urql, передавая values формы в тело запроса.

Пример GraphQL-запроса:

const handleSubmit = async (values) => {
  const query = `
    mutation CreateUser($input: UserInput!) {
      createUser(input: $input) { id name email }
    }
  `;
  const variables = { input: values };
  const response = await fetch('/graphql', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ query, variables }),
  });
  const result = await response.json();
  console.log(result.data);
};
  • Значения формы напрямую становятся переменными GraphQL-запроса.
  • Можно использовать те же механизмы loading, message и setFields для обработки состояний и ошибок.

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