Submit и обработка отправки

Radix UI предоставляет низкоуровневые, доступные компоненты для создания интерфейсов на React. Одним из ключевых аспектов интерактивных элементов форм является управление отправкой данных и интеграция с обработчиками событий формы. В Radix UI нет собственной системы управления формами, но его компоненты легко сочетаются с нативными <form> элементами и библиотеками управления состоянием, такими как React Hook Form или Formik.

Работа с onSubmit

Для корректной обработки отправки формы важно понимать базовый паттерн работы с onSubmit в React:

function FormComponent() {
  const handleSubmit = (event) => {
    event.preventDefault();
    const formData = new FormData(event.target);
    const data = Object.fromEntries(formData.entries());
    console.log(data);
  };

  return (
    <form onSub mit={handleSubmit}>
      <input name="username" type="text" />
      <input name="email" type="email" />
      <button type="submit">Отправить</button>
    </form>
  );
}
  • event.preventDefault() предотвращает стандартное поведение браузера (перезагрузку страницы).
  • FormData позволяет легко собрать данные формы для последующей обработки или отправки на сервер.

Интеграция с компонентами Radix UI

Компоненты Radix UI часто используются для кастомных UI-элементов, таких как кнопки, переключатели или модальные окна. Для Submit важно убедиться, что кнопка внутри формы имеет type="submit":

import * as Button from '@radix-ui/react-button';

<form onSub mit={handleSubmit}>
  <input name="username" type="text" />
  <Button.Root type="submit">Отправить</Button.Root>
</form>
  • Button.Root наследует поведение нативного <button> и может быть безопасно использован для отправки формы.
  • При кастомных компонентах, не являющихся <button>, нужно вручную вызвать form.submit() или использовать onClick, чтобы инициировать отправку.

Работа с асинхронной отправкой

В реальных приложениях часто требуется отправка данных через API. Асинхронная обработка выполняется внутри handleSubmit:

const handleSubmit = async (event) => {
  event.preventDefault();
  const formData = new FormData(event.target);
  const data = Object.fromEntries(formData.entries());

  try {
    const response = await fetch('/api/submit', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(data),
    });
    if (!response.ok) throw new Error('Ошибка при отправке');
    const result = await response.json();
    console.log('Успешно отправлено', result);
  } catch (error) {
    console.error(error);
  }
};
  • Асинхронная функция позволяет работать с await, что упрощает чтение кода.
  • Обработка ошибок с try/catch обеспечивает безопасную работу с сетевыми запросами.

Интеграция с Radix Dialog для форм

Модальные окна Radix UI (Dialog) часто содержат формы. При этом важно следовать следующей структуре:

import * as Dialog from '@radix-ui/react-dialog';
import * as Button from '@radix-ui/react-button';

<Dialog.Root>
  <Dialog.Trigger asChild>
    <Button.Root>Открыть форму</Button.Root>
  </Dialog.Trigger>
  <Dialog.Content>
    <form onSub mit={handleSubmit}>
      <input name="username" type="text" />
      <Button.Root type="submit">Отправить</Button.Root>
    </form>
  </Dialog.Content>
</Dialog.Root>
  • Dialog.Trigger с asChild позволяет использовать кастомные кнопки для открытия модального окна.
  • Dialog.Content не мешает стандартной отправке формы, если внутри находится <form> с корректным onSubmit.

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

Radix UI не предоставляет собственного state-менеджера для форм, но компоненты могут быть связаны с React Hook Form:

import { useForm } from 'react-hook-form';
import * as Button from '@radix-ui/react-button';

function HookFormComponent() {
  const { register, handleSubmit } = useForm();

  const onSub mit = data => console.log(data);

  return (
    <form onSub mit={handleSubmit(onSubmit)}>
      <input {...register('username')} />
      <Button.Root type="submit">Отправить</Button.Root>
    </form>
  );
}
  • Использование register автоматически связывает поля с внутренним состоянием.
  • handleSubmit из React Hook Form обеспечивает валидацию перед отправкой.

Валидация и обратная связь

Для комплексных форм необходимо показывать ошибки и статус отправки. Например:

const [isSubmitting, setIsSubmitting] = useState(false);
const [error, setError] = useState(null);

const handleSubmit = async (event) => {
  event.preventDefault();
  setIsSubmitting(true);
  setError(null);
  
  try {
    const data = Object.fromEntries(new FormData(event.target).entries());
    const response = await fetch('/api/submit', {
      method: 'POST',
      body: JSON.stringify(data),
      headers: { 'Content-Type': 'application/json' },
    });
    if (!response.ok) throw new Error('Ошибка сети');
  } catch (err) {
    setError(err.message);
  } finally {
    setIsSubmitting(false);
  }
};
  • isSubmitting позволяет блокировать кнопку отправки во время ожидания ответа.
  • Переменная error обеспечивает вывод сообщений пользователю.

Советы по структуре форм с Radix UI

  • Всегда использовать type="submit" для кнопок отправки.
  • Компоненты Radix UI можно использовать как оболочку для стандартных элементов формы (input, select).
  • Для сложных форм интегрировать с библиотеками управления состоянием и валидацией.
  • Обрабатывать асинхронные отправки с try/catch и предусматривать индикаторы загрузки.
  • Для модальных форм следить, чтобы Dialog.Content содержал стандартный <form> с корректным onSubmit.

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