Server Action + маягт
Өмнөх хичээлд Server Action-г button click дээр дуудах аргыг суралцсан. Энэ хичээлд Server Action-г HTML <form> элементтэй хослуулна. Энэ хослол нь JavaScript ажиллахгүй байсан ч form-г зөв ажилладаг болгодог — веб хөгжүүлэлтийн хамгийн найдвартай загвар.
form action шинж чанар
HTML <form> элементийн action шинж чанарт Server Action шууд дамжуулж болно:
// app/profile/page.tsx
import { updateUsername } from "@/app/actions";
export default function ProfilePage() {
return (
<form action={updateUsername}>
<label>
Хэрэглэгчийн нэр
<input type="text" name="username" required />
</label>
<button type="submit">Хадгалах</button>
</form>
);
}
// app/actions.ts
"use server";
import { createClient } from "@/lib/supabase/server";
import { revalidatePath } from "next/cache";
export async function updateUsername(formData: FormData) {
const username = formData.get("username") as string;
if (!username || username.length < 3) {
throw new Error("Хэрэглэгчийн нэр хэт богино байна");
}
const supabase = await createClient();
const {
data: { user },
} = await supabase.auth.getUser();
if (!user) throw new Error("Нэвтрээгүй байна");
await supabase.from("profiles").update({ username }).eq("id", user.id);
revalidatePath("/profile");
}
action={updateUsername} гэж бичихэд form submit хийгдэх үед Next.js автоматаар FormData-г updateUsername функцэд дамжуулна.
useActionState — form-н төлөв удирдах
Алдаа харуулах, амжилтын мэдэгдэл гаргах зэрэгт React-н useActionState hook ашигладаг:
"use client";
import { useActionState } from "react";
import { updateUsername } from "@/app/actions";
interface ActionState {
error?: string;
success?: boolean;
}
export default function UsernameForm() {
const [state, formAction, isPending] = useActionState<ActionState, FormData>(
async (_prev, formData) => {
try {
await updateUsername(formData);
return { success: true };
} catch (err) {
return { error: (err as Error).message };
}
},
{},
);
return (
<form action={formAction}>
<label>
Хэрэглэгчийн нэр
<input type="text" name="username" required />
</label>
{state.error && <p style={{ color: "red" }}>{state.error}</p>}
{state.success && (
<p style={{ color: "green" }}>Амжилттай хадгалагдлаа!</p>
)}
<button type="submit" disabled={isPending}>
{isPending ? "Хадгалж байна..." : "Хадгалах"}
</button>
</form>
);
}
useActionState гурван зүйл буцаана:
state— өмнөх action-н үр дүн (алдаа эсвэл амжилт)formAction— form-нactionшинж чанарт өгөх функцisPending— action одоо ажиллаж байгаа эсэх
useFormStatus — submit товч
useFormStatus hook нь form дотор submit-н төлөвийг мэдэхэд хэрэглэнэ. Тусдаа component болгон гаргах нь ухаалаг:
"use client";
import { useFormStatus } from "react-dom";
export function SubmitButton({ label }: { label: string }) {
const { pending } = useFormStatus();
return (
<button type="submit" disabled={pending}>
{pending ? "Хадгалж байна..." : label}
</button>
);
}
// UsernameForm дотор ашиглах
import { SubmitButton } from "@/components/ui/SubmitButton";
<form action={formAction}>
<input type="text" name="username" required />
<SubmitButton label="Хадгалах" />
</form>;
SubmitButton-г хаана ч ашиглаж болно — useFormStatus автоматаар ойрын form-н төлөвийг мэдэрдэг.
Дараагийн хичээлд:
API Route Handler бичиж сурна. Гадны сервис, webhook, mobile app-тай холбоход хэрэгтэй REST endpoint хэрхэн үүсгэхийг ойлгоно.