Компонент Form в React Router
представляет собой специализированный элемент для работы с формами,
который интегрирован с маршрутизацией и механизмами обработки данных на
стороне маршрутов. Он упрощает отправку данных, позволяя использовать
стандартные HTML-формы вместе с функциями маршрутизатора, такими как
action в маршрутах.
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 данные формы сериализуются
в 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>;
}
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 на вложенном маршруте.