В современном веб-разработке обработка форм и передача данных с клиента на сервер являются ключевыми задачами. React Router начиная с версии 6.4 предоставляет мощные инструменты для работы с формами через actions, позволяя интегрировать отправку данных и навигацию без использования сторонних библиотек.
FormData — это стандартный объект JavaScript,
который позволяет собирать пары ключ-значение из формы, включая файлы, и
передавать их в HTTP-запросах. В контексте React Router FormData
используется вместе с формами, определёнными компонентом
<Form>.
Пример создания FormData вручную:
const formElement = document.querySelector('form');
const data = new FormData(formElement);
Каждое поле формы автоматически добавляется в объект
FormData, включая файлы:
data.append('username', 'JohnDoe');
data.append('avatar', fileInput.files[0]);
<Form> в React RouterВ React Router компонент <Form> заменяет привычный
HTML <form> и автоматически интегрируется с
маршрутизатором. Основные особенности:
method указывает HTTP-метод (post,
put, patch, delete).action определяет маршрут, на который будет
отправлен запрос.<Form> можно использовать обычные элементы
<input>, <select>,
<textarea>.Пример использования:
import { Form } from "react-router-dom";
<Form method="post" action="/submit">
<input name="username" type="text" />
<input name="email" type="email" />
<input name="avatar" type="file" />
<button type="submit">Отправить</button>
</Form>
При отправке данных React Router автоматически собирает их в объект
FormData и передаёт в action маршрута.
Action — это функция, привязанная к маршруту, которая обрабатывает данные формы до того, как произойдёт навигация. Она получает объект Request, из которого можно извлечь данные формы:
export async function action({ request }) {
const formData = await request.formData();
const username = formData.get('username');
const email = formData.get('email');
const avatar = formData.get('avatar');
// Дальнейшая обработка, например, отправка на сервер
await fetch('/api/users', {
method: 'POST',
body: formData
});
return null;
}
Особенности работы с файлами: FormData
корректно передаёт файлы без необходимости ручного создания
multipart-запроса. Можно одновременно передавать текстовые поля и файлы
в одном объекте FormData.
React Router позволяет вернуть ошибки из action, используя объект
json или redirect:
import { json } from "react-router-dom";
export async function action({ request }) {
const formData = await request.formData();
const username = formData.get('username');
if (!username) {
return json({ error: "Имя пользователя обязательно" }, { status: 400 });
}
// Сохранение данных
return null;
}
На клиентской стороне можно использовать useActionData
для получения ошибок и их отображения:
import { useActionData } from "react-router-dom";
const actionData = useActionData();
return (
<div>
{actionData?.error && <p>{actionData.error}</p>}
<Form method="post">
<input name="username" />
<button type="submit">Отправить</button>
</Form>
</div>
);
Для больших файлов и длительных операций рекомендуется использовать
fetch с объектом FormData внутри action. Можно
использовать AbortController для отмены загрузки:
export async function action({ request }) {
const formData = await request.formData();
const controller = new AbortController();
try {
await fetch('/api/upload', {
method: 'POST',
body: formData,
signal: controller.signal
});
} catch (error) {
if (error.name === 'AbortError') {
console.log('Загрузка отменена');
} else {
throw error;
}
}
return null;
}
Иногда требуется формировать FormData программно, без
использования <Form>. В этом случае можно создать
объект и передать его через fetch или через custom
action:
const formData = new FormData();
formData.append('name', 'Alice');
formData.append('profile', fileInput.files[0]);
await fetch('/api/profile', { method: 'POST', body: formData });
<Form> автоматически блокирует перезагрузку
страницы при отправке.FormData с action позволяет сохранять
SPA-поведение.<input type="file">, автоматически добавляются в
FormData.FormData вне
<Form>, но в этом случае необходимо самостоятельно
вызывать fetch и обрабатывать навигацию.FormData позволяет объединять текстовые поля и файлы в
одном объекте.<Form> React Router интегрируется с
маршрутизатором и поддерживает отправку FormData.Request и может асинхронно
обрабатывать данные.json, а клиент
получать через useActionData.FormData вручную и использовать fetch.Работа с FormData в React Router позволяет реализовать современную SPA-архитектуру, объединяя формы, асинхронные операции и обработку навигации без перезагрузки страницы, сохраняя чистый и удобный код.