Server Action үндэс
Өмнөх хичээлүүдэд Server Component ашиглан өгөгдөл унших аргыг суралцсан. Харин өгөгдөл бичих — form submit хийх, өгөгдлийн санд хадгалах — ямар байдаг вэ? Тэр асуултын хариулт бол Server Action юм.
Server Action гэж юу вэ?
Server Action бол серверт ажилладаг async function бөгөөд клиентээс шууд дуудаж болдог. API route бичихгүйгээр клиент → сервер холболтыг хийдэг.
Тайлбарлавал:
Ердийн арга (хуучин): Server Action (шинэ):
Client component Client component
↓ fetch('/api/save', ...) ↓ шууд функц дуудна
API route (/api/save) Server дээр ажилладаг функц
↓ ↓
Database Database
Server Action нь 'use server' directive-тэй байдаг:
// app/actions.ts
"use server";
import { createClient } from "@/lib/supabase/server";
export async function saveProgress(courseSlug: string, lessonSlug: string) {
const supabase = await createClient();
const {
data: { user },
} = await supabase.auth.getUser();
if (!user) throw new Error("Нэвтрээгүй байна");
const { error } = await supabase.from("lesson_progress").upsert({
user_id: user.id,
course_slug: courseSlug,
lesson_slug: lessonSlug,
});
if (error) throw new Error("Хадгалахад алдаа гарлаа");
return { success: true };
}
'use server' гэдэг нь "энэ файл дахь функцүүд зөвхөн серверт ажиллана" гэсэн утгатай.
Client component-оос дуудах
Server Action-г Client component дотор энгийн функц шиг дуудна:
"use client";
import { useState } from "react";
import { saveProgress } from "@/app/actions";
interface Props {
courseSlug: string;
lessonSlug: string;
}
export default function CompleteButton({ courseSlug, lessonSlug }: Props) {
const [loading, setLoading] = useState(false);
const [done, setDone] = useState(false);
async function handleComplete() {
setLoading(true);
try {
await saveProgress(courseSlug, lessonSlug);
setDone(true);
} catch (err) {
console.error(err);
} finally {
setLoading(false);
}
}
return (
<button onClick={handleComplete} disabled={loading || done}>
{done
? "Хичээл дууссан — +10 XP"
: loading
? "Хадгалж байна..."
: "Дуусгах"}
</button>
);
}
Харна уу — fetch, JSON.stringify, API route нэг ч байхгүй. Зүгээр л функц дуудлаа.
Server Action дотор cache шинэчлэх
Server Action ажилласны дараа холбогдох хуудасны кэшийг шинэчлэх хэрэгтэй бол revalidatePath дуудна:
"use server";
import { revalidatePath } from "next/cache";
import { createClient } from "@/lib/supabase/server";
export async function saveProgress(courseSlug: string, lessonSlug: string) {
const supabase = await createClient();
const {
data: { user },
} = await supabase.auth.getUser();
if (!user) throw new Error("Нэвтрээгүй байна");
await supabase.from("lesson_progress").upsert({
user_id: user.id,
course_slug: courseSlug,
lesson_slug: lessonSlug,
});
// профайл хуудасны кэшийг шинэчлэнэ
revalidatePath("/profile");
return { success: true };
}
Хэрэглэгч хичээл дуусгасны дараа /profile хуудас руу орвол шинэ дэвшлийг харах болно.
Дараагийн хичээлд:
Server Action-г HTML <form> элементтэй хослуулах аргыг судална. JavaScript идэвхгүй байсан ч ажилладаг, хэрэглэгчийн туршлага маш сайн form бичиж сурна.