Async-операции в модальных окнах

Модальные окна в Ant Design (Modal) предоставляют гибкий инструмент для отображения диалогов с пользователем. Одним из ключевых аспектов работы с модальными окнами является управление асинхронными операциями, такими как запросы к серверу, задержки или обработка данных перед закрытием окна. Понимание правильного подхода к асинхронности позволяет создавать интерфейсы с отзывчивой логикой и корректным пользовательским опытом.


Использование okButtonProps и confirmLoading

Компонент Modal поддерживает встроенную интеграцию с асинхронными действиями через свойство confirmLoading. Оно предназначено для отображения состояния загрузки на кнопке подтверждения (OK), пока выполняется асинхронная операция.

Пример:

import React, { useState } from 'react';
import { Modal, Button, message } from 'antd';

const AsyncModalExample = () => {
  const [visible, setVisible] = useState(false);
  const [confirmLoading, setConfirmLoading] = useState(false);

  const handleOk = async () => {
    setConfirmLoading(true);
    try {
      await new Promise(resolve => setTimeout(resolve, 2000)); // эмуляция запроса
      message.success('Операция завершена успешно');
      setVisible(false);
    } catch (error) {
      message.error('Произошла ошибка');
    } finally {
      setConfirmLoading(false);
    }
  };

  return (
    <>
      <Button type="primary" onCl ick={() => setVisible(true)}>
        Открыть модальное окно
      </Button>
      <Modal
        title="Асинхронная операция"
        visible={visible}
        onOk={handleOk}
        confirmLoading={confirmLoading}
        onCan cel={() => setVisible(false)}
      >
        <p>Нажмите "OK" для запуска асинхронной операции.</p>
      </Modal>
    </>
  );
};

export default AsyncModalExample;

Особенности данного подхода:

  • confirmLoading управляет состоянием кнопки OK, блокируя повторные клики.
  • Асинхронный код в handleOk позволяет безопасно обрабатывать промисы и отображать уведомления о результате.
  • Закрытие модального окна (setVisible(false)) происходит только после завершения операции.

Асинхронные операции перед закрытием модального окна

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

const handleOk = async () => {
  setConfirmLoading(true);
  try {
    const result = await fetch('/api/save', { method: 'POST' });
    if (!result.ok) throw new Error('Ошибка сохранения');
    setVisible(false);
    message.success('Данные успешно сохранены');
  } catch (err) {
    message.error(err.message);
  } finally {
    setConfirmLoading(false);
  }
};

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

  • Асинхронный вызов перед закрытием позволяет корректно обрабатывать ошибки и уведомления.
  • Modal не закрывается автоматически, пока setVisible(false) не вызван.
  • Поддержка состояния confirmLoading улучшает UX, показывая пользователю, что операция в процессе.

Использование Form внутри модального окна с асинхронной отправкой

Частый сценарий — форма внутри модального окна, где кнопка OK выполняет асинхронную отправку данных.

import { Form, Input } from 'antd';

const FormModal = () => {
  const [visible, setVisible] = useState(false);
  const [confirmLoading, setConfirmLoading] = useState(false);
  const [form] = Form.useForm();

  const handleOk = async () => {
    try {
      const values = await form.validateFields();
      setConfirmLoading(true);
      await saveData(values); // асинхронная функция сохранения
      message.success('Форма успешно отправлена');
      setVisible(false);
      form.resetFields();
    } catch (err) {
      message.error('Ошибка при отправке формы');
    } finally {
      setConfirmLoading(false);
    }
  };

  return (
    <>
      <Button onCl ick={() => setVisible(true)}>Открыть форму</Button>
      <Modal
        visible={visible}
        title="Форма с асинхронной отправкой"
        onOk={handleOk}
        confirmLoading={confirmLoading}
        onCan cel={() => setVisible(false)}
      >
        <Form form={form} layout="vertical">
          <Form.Item
            name="username"
            label="Имя пользователя"
            rules={[{ required: true, message: 'Введите имя пользователя' }]}
          >
            <Input />
          </Form.Item>
        </Form>
      </Modal>
    </>
  );
};

Особенности подхода с Form:

  • Асинхронная отправка данных возможна только после успешной валидации формы (validateFields).
  • confirmLoading предотвращает повторные отправки при долгой обработке.
  • Сброс полей формы (form.resetFields()) после успешной операции гарантирует чистое состояние при следующем открытии модального окна.

Рекомендации по UX при асинхронных операциях в модальных окнах

  1. Обеспечить обратную связь пользователю: использовать message, notification или Spin внутри модального окна.
  2. Блокировать повторные клики на кнопке OK с помощью confirmLoading.
  3. Не закрывать модальное окно автоматически при ошибках — пользователь должен увидеть причину ошибки.
  4. Очистка состояния после закрытия: сброс форм и локальных переменных предотвращает неожиданные данные при следующем открытии.
  5. Разделение логики отображения и обработки: модальное окно управляет только UI, а асинхронная логика может быть вынесена в отдельные функции или сервисы.

Использование кастомных кнопок с асинхронной логикой

Иногда стандартной кнопки OK недостаточно, и требуется реализовать кастомные кнопки с собственными асинхронными обработчиками:

<Modal
  visible={visible}
  title="Кастомные действия"
  footer={[
    <Button key="back" onCl ick={() => setVisible(false)}>
      Отмена
    </Button>,
    <Button
      key="submit"
      type="primary"
      loading={confirmLoading}
      onCl ick={async () => {
        setConfirmLoading(true);
        await doAsyncTask();
        setConfirmLoading(false);
        setVisible(false);
      }}
    >
      Сохранить
    </Button>,
  ]}
>
  <p>Модальное окно с кастомными кнопками и асинхронными действиями.</p>
</Modal>

Преимущества кастомного футера:

  • Возможность реализовать несколько асинхронных действий с разной логикой.
  • Полный контроль над состоянием каждой кнопки (loading, disabled).
  • Легкость интеграции с внешними сервисами и API.

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