Компонент Form

Компонент Form в React Router представляет собой специализированный элемент для работы с формами, который интегрирован с маршрутизацией и механизмами обработки данных на стороне маршрутов. Он упрощает отправку данных, позволяя использовать стандартные HTML-формы вместе с функциями маршрутизатора, такими как action в маршрутах.

Основные свойства компонента Form

  • method Определяет HTTP-метод, который будет использоваться при отправке формы. Поддерживаются стандартные значения:

    • "get" — данные передаются через URL-параметры.
    • "post" — данные отправляются в теле запроса.
    • "put", "patch", "delete" — поддерживаются для взаимодействия с action маршрута.
  • action Задает путь маршрута, в котором будет вызвана функция action. Если не указан, форма отправляется в текущий маршрут.

  • replace Логическое значение. Если true, текущий переход заменяет запись в истории браузера вместо добавления новой.

  • encType Определяет тип кодирования данных формы (аналогично стандартному enctype в HTML):

    • "application/x-www-form-urlencoded" — по умолчанию.
    • "multipart/form-data" — для загрузки файлов.
    • "text/plain" — редко используется.
  • reloadDocument Если установлено в true, форма будет работать как обычная HTML-форма, перезагружая страницу, а не используя SPA-навигацию.

Пример базового использования

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

function ContactForm() {
  return (
    <Form method="post" action="/contact">
      <label>
        Имя:
        <input type="text" name="name" />
      </label>
      <label>
        Сообщение:
        <textarea name="message"></textarea>
      </label>
      <button type="submit">Отправить</button>
    </Form>
  );
}

В этом примере при нажатии на кнопку submit данные формы будут переданы в action маршрута /contact.

Интеграция с функциями action маршрутов

React Router позволяет объявлять функции action в объекте маршрута, которые будут обрабатывать отправленные формы. Пример маршрута с action:

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

export async function contactAction({ request }) {
  const formData = await request.formData();
  const name = formData.get("name");
  const message = formData.get("message");

  // Здесь можно сохранить данные в базу или выполнить другие операции
  console.log({ name, message });

  return redirect("/thank-you");
}

Компонент Form автоматически собирает данные и передает их в request.formData() функции action.

Работа с GET-запросами

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

<Form method="get" action="/search">
  <input type="text" name="query" placeholder="Поиск..." />
  <button type="submit">Искать</button>
</Form>

В маршруте /search можно извлечь параметры через useSearchParams:

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

function SearchResults() {
  const [searchParams] = useSearchParams();
  const query = searchParams.get("query");

  return <div>Результаты поиска для: {query}</div>;
}

Асинхронная обработка и блокировка UI

Form поддерживает асинхронные операции внутри action. Пока action выполняется, можно отслеживать состояние через useNavigation:

import { Form, useNavigation } from "react-router-dom";

function ContactForm() {
  const navigation = useNavigation();
  const isSubmitting = navigation.state === "submitting";

  return (
    <Form method="post" action="/contact">
      <input type="text" name="name" disabled={isSubmitting} />
      <textarea name="message" disabled={isSubmitting}></textarea>
      <button type="submit" disabled={isSubmitting}>
        {isSubmitting ? "Отправка..." : "Отправить"}
      </button>
    </Form>
  );
}

Это позволяет предотвратить повторные отправки формы и улучшает UX.

Поддержка файлов

Для загрузки файлов необходимо указать encType="multipart/form-data" и использовать input с type="file":

<Form method="post" action="/upload" encType="multipart/form-data">
  <input type="file" name="avatar" />
  <button type="submit">Загрузить</button>
</Form>

В action можно получить файл через request.formData().get("avatar").

Использование вложенных форм

React Router поддерживает вложенные маршруты и вложенные формы. Каждая форма отправляет данные в ближайший маршрут с определенной функцией action. Это позволяет создавать комплексные интерфейсы с несколькими формами на одной странице без конфликтов.

<Route path="dashboard" element={<DashboardLayout />} action={dashboardAction}>
  <Route path="profile" element={<ProfileForm />} action={profileAction} />
  <Route path="settings" element={<SettingsForm />} action={settingsAction} />
</Route>

Форма ProfileForm отправит данные в profileAction, а не в dashboardAction, если указано action на вложенном маршруте.

Ключевые преимущества компонента Form

  • Интеграция с маршрутизатором без ручной обработки событий.
  • Поддержка SPA-навигации и асинхронных операций.
  • Удобная работа с GET и POST методами.
  • Возможность блокировать UI во время отправки.
  • Поддержка вложенных маршрутов и разделения ответственности по обработке форм.