useSubmit для программной отправки форм

В React Router начиная с версии 6.4 появилась возможность работать с формами не только через обычные HTML-элементы <form> с событиями onSubmit, но и программно, используя хук useSubmit. Этот подход позволяет выполнять навигацию и отправку данных без прямого участия пользователя, сохраняя преимущества маршрутизации и загрузки данных через маршруты.


Основы useSubmit

Хук useSubmit импортируется из пакета react-router-dom:

import { useSubmit } from "react-router-dom";

Он возвращает функцию, которая позволяет отправлять данные на текущий маршрут или на другой маршрут без использования стандартного <form>.

Сигнатура функции submit:

submit(
  target: HTMLFormElement | FormData | URLSearchParams | Object,
  options?: {
    method?: "get" | "post" | "put" | "patch" | "delete";
    action?: string;
    encType?: string;
    replace?: boolean;
  }
)
  • target — источник данных. Может быть элемент <form>, объект FormData, URLSearchParams или обычный объект.
  • method — HTTP-метод для отправки данных, по умолчанию "post".
  • action — маршрут, на который будет отправлен запрос. По умолчанию используется текущий маршрут.
  • encType — тип кодирования данных, аналогично атрибуту enctype в HTML.
  • replace — если true, история навигации заменяется вместо добавления новой записи.

Использование с элементом <form>

Самый простой способ — передать в submit ссылку на форму:

import { useSubmit } from "react-router-dom";

function ContactForm() {
  const submit = useSubmit();

  const handleClick = () => {
    const form = document.getElementById("contact-form");
    submit(form);
  };

  return (
    <form id="contact-form">
      <input name="name" />
      <input name="email" />
      <button type="button" onCl ick={handleClick}>
        Отправить
      </button>
    </form>
  );
}

В этом примере форма не отправляется стандартным способом, а программно через submit(form). React Router обработает данные так же, как если бы форма была отправлена через <Form method="post">.


Отправка данных из объекта или FormData

Иногда нет необходимости использовать реальный <form> на странице. Можно собрать данные в объекте или FormData и отправить их напрямую:

function NewsletterSignup() {
  const submit = useSubmit();

  const handleSignup = () => {
    const data = { email: "user@example.com" };
    submit(data, { method: "post", action: "/signup" });
  };

  return (
    <button onCl ick={handleSignup}>Подписаться</button>
  );
}

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

  • При использовании объекта { key: value } React Router автоматически преобразует его в FormData.
  • Можно задавать метод get или post для соответствия логике маршрута.

Работа с асинхронными обработчиками (action)

useSubmit тесно интегрирован с системой action в маршрутах React Router. Отправка данных через submit вызовет соответствующий обработчик:

// В маршруте
{
  path: "/signup",
  element: <NewsletterSignup />,
  action: async ({ request }) => {
    const formData = await request.formData();
    const email = formData.get("email");
    await apiSubscribe(email);
    return { success: true };
  }
}

Таким образом, отправка через submit полностью поддерживает серверную или клиентскую обработку данных маршрута.


Дополнительные параметры

  • replace: true — позволяет обновлять текущий маршрут без создания новой записи в истории, полезно для обновления данных формы без возможности возврата.
  • encType — полезно при работе с файлами, например multipart/form-data.
const formData = new FormData();
formData.append("file", fileInput.files[0]);

submit(formData, { method: "post", encType: "multipart/form-data" });

Примеры типичных сценариев

  1. Отправка без <form> для динамических интерфейсов:
const data = { search: query };
submit(data, { method: "get", action: "/search" });
  1. Программное подтверждение формы перед отправкой:
if (window.confirm("Вы уверены?")) {
  submit(formElement);
}
  1. Отправка файлов через FormData с replace для обновления контента:
const fd = new FormData();
fd.append("avatar", file);
submit(fd, { method: "post", encType: "multipart/form-data", replace: true });

Ключевые преимущества useSubmit

  • Полная интеграция с маршрутизатором: данные маршрутов, action и навигация работают автоматически.
  • Возможность отправки программно без HTML-форм.
  • Гибкость методов и маршрутов.
  • Поддержка отправки как простых объектов, так и сложных FormData с файлами.
  • Управление историей навигации через replace.

useSubmit предоставляет мощный инструмент для управления формами в React Router, объединяя преимущества SPA и привычной работы с формами HTML. Он позволяет создавать динамичные интерфейсы с гибким контролем отправки данных и интеграцией с маршрутизатором.