Server Actions Nedir?
Server Actions, form submit işlemlerinin doğrudan sunucuda çalışmasını sağlar. API endpoint yazmadan, client-side JavaScript olmadan form verilerini işleyebilirsiniz.
Temel Server Action
// app/iletisim/page.tsx
export default function IletisimFormu() {
// Server Action — "use server" direktifi ile
async function formuGonder(formData: FormData) {
"use server";
const isim = formData.get("isim") as string;
const mesaj = formData.get("mesaj") as string;
// Sunucuda çalışır — DB, email, vb.
await emailGonder({ isim, mesaj });
console.log(`Mesaj alındı: ${isim} — ${mesaj}`);
}
return (
<form action={formuGonder}>
<input name="isim" placeholder="Adınız" required />
<textarea name="mesaj" placeholder="Mesajınız" required />
<button type="submit">Gönder</button>
</form>
);
}
useActionState ile Durum Yönetimi
"use client";
import { useActionState } from "react";
async function girisYap(prevState: any, formData: FormData) {
"use server";
const email = formData.get("email") as string;
const sifre = formData.get("sifre") as string;
if (sifre.length < 8) {
return { hata: "Şifre en az 8 karakter olmalı" };
}
// Giriş işlemi...
return { basari: true };
}
export default function GirisFormu() {
const [durum, action, bekliyor] = useActionState(girisYap, null);
return (
<form action={action}>
{durum?.hata && (
<p className="text-red-500">{durum.hata}</p>
)}
{durum?.basari && (
<p className="text-green-500">Giriş başarılı!</p>
)}
<input name="email" type="email" required />
<input name="sifre" type="password" required />
<button disabled={bekliyor}>
{bekliyor ? "Giriş yapılıyor..." : "Giriş Yap"}
</button>
</form>
);
}
useOptimistic ile Anlık UI Güncellemesi
"use client";
import { useOptimistic } from "react";
export default function YorumListesi({ yorumlar }: { yorumlar: Yorum[] }) {
const [optimistikYorumlar, yorumEkle] = useOptimistic(
yorumlar,
(mevcutYorumlar, yeniYorum: Yorum) => [...mevcutYorumlar, yeniYorum]
);
async function yorumGonder(formData: FormData) {
"use server";
const metin = formData.get("metin") as string;
// Anında UI güncellenir, sunucu cevabını beklemez
yorumEkle({ id: Date.now(), metin, bekliyor: true });
await yorumuKaydet(metin);
}
return (
<div>
{optimistikYorumlar.map(y => (
<p key={y.id} className={y.bekliyor ? "opacity-50" : ""}>
{y.metin}
</p>
))}
<form action={yorumGonder}>
<input name="metin" />
<button>Yorum Yap</button>
</form>
</div>
);
}
Ayrı actions.ts Dosyası
// app/actions.ts
"use server";
import { revalidatePath } from "next/cache";
export async function urunEkle(formData: FormData) {
const isim = formData.get("isim") as string;
await veritabanineEkle({ isim });
revalidatePath("/urunler"); // Cache temizle, sayfayı yenile
}
export async function urunSil(id: number) {
await veritabanindenSil(id);
revalidatePath("/urunler");
}
Önemli Noktalar
- "use server" direktifi ile Server Action tanımlanır
- form action'ına Server Action atanır — API endpoint gerekmez
- useActionState ile form durumu (hata/başarı/bekliyor) yönetilir
- revalidatePath ile önbellek temizlenerek sayfa yenilenir