5. Actions: мутации данных
action — серверная функция для обработки мутаций: создания, обновления, удаления данных. Вызывается при отправке формы через <Form method="post">.
Базовый action
Заголовок раздела «Базовый action»import { json, redirect } from "@remix-run/node";import { Form, useActionData } from "@remix-run/react";
export async function action({ request }) { const formData = await request.formData(); const name = formData.get("name") as string; const email = formData.get("email") as string;
// Валидация if (!name || name.length < 2) { return json({ error: "Имя слишком короткое" }, { status: 400 }); }
// Сохранение await db.user.create({ data: { name, email } });
// Редирект после успеха return redirect("/users");}
export default function NewUser() { const actionData = useActionData<typeof action>();
return ( <Form method="post"> <input name="name" placeholder="Имя" /> <input name="email" placeholder="Email" /> {actionData?.error && <p>{actionData.error}</p>} <button type="submit">Создать</button> </Form> );}Несколько action в одном маршруте
Заголовок раздела «Несколько action в одном маршруте»export async function action({ request }) { const formData = await request.formData(); const intent = formData.get("intent");
switch (intent) { case "create": return createUser(formData); case "delete": return deleteUser(formData.get("id") as string); case "update": return updateUser(formData); default: return json({ error: "Неизвестное действие" }, { status: 400 }); }}
// В компоненте:<Form method="post"> <button name="intent" value="create">Создать</button></Form><Form method="post"> <input type="hidden" name="id" value={user.id} /> <button name="intent" value="delete">Удалить</button></Form>Валидация с zod
Заголовок раздела «Валидация с zod»import { z } from "zod";import { parseWithZod } from "@conform-to/zod";
const schema = z.object({ email: z.string().email("Неверный email"), password: z.string().min(8, "Минимум 8 символов"),});
export async function action({ request }) { const formData = await request.formData(); const submission = parseWithZod(formData, { schema });
if (submission.status !== "success") { return json(submission.reply()); }
// Данные валидны const { email, password } = submission.value; await createUser({ email, password }); return redirect("/dashboard");}useSubmit — программная отправка
Заголовок раздела «useSubmit — программная отправка»import { useSubmit } from "@remix-run/react";
export default function AutoSave() { const submit = useSubmit();
function handleChange(event) { submit(event.currentTarget, { method: "post", debounce: 500, // через 500ms после последнего изменения }); }
return ( <Form method="post" onChange={handleChange}> <textarea name="content" /> </Form> );}