revalidatePath & redirect
Refresh data dan pindah halaman setelah Server Action sukses.
Kenapa datamu tidak berubah sendiri?
Next.js meng-cache hasil fetch di Server Component secara agresif. Itu bagus untuk kecepatan, tapi menimbulkan masalah klasik: user menambah todo lewat Server Action, halaman di-render ulang, tapi daftarnya masih yang lama karena Next.js menyajikan cache basi. Kamu harus memberi tahu Next.js: "cache untuk halaman ini sudah tidak valid, fetch ulang." Di sinilah revalidatePath berperan.
revalidatePath: tandai cache sebagai basi
Panggil ia di akhir Server Action setelah mutasi berhasil:
// app/todos/actions.ts
"use server";
import { revalidatePath } from "next/cache";
export async function tambahTodo(formData: FormData) {
const judul = String(formData.get("judul") ?? "").trim();
if (!judul) return { error: "Judul tidak boleh kosong" };
await db.todo.create({ judul });
revalidatePath("/todos"); // request berikutnya ke /todos fetch ulang
}revalidatePath menerima argumen kedua yang berguna: "page" atau "layout". revalidatePath("/blog", "layout") me-revalidasi layout /blog beserta semua halaman di bawahnya, berguna kalau data berubah di level layout (misalnya jumlah notifikasi di sidebar).
revalidateTag: untuk data yang dipakai banyak halaman
Kalau satu data tampil di banyak halaman (misalnya info produk muncul di homepage, halaman kategori, dan halaman detail), me-revalidate satu path tidak cukup. Solusinya: beri tag saat fetch, lalu revalidasi per tag:
// app/produk/actions.ts
"use server";
import { revalidateTag } from "next/cache";
// saat fetch di page: fetch(url, { next: { tags: ["produk"] } })
export async function updateProduk(id: string, formData: FormData) {
await db.produk.update(id, { nama: String(formData.get("nama")) });
revalidateTag("produk"); // semua halaman yang fetch tag ini di-refresh
}Aturan praktisnya: satu-dua halaman terpengaruh, pakai revalidatePath; data disharing banyak tempat, pakai revalidateTag.
redirect: pindah halaman dari server
Setelah login sukses, kamu ingin user langsung mendarat di dashboard. redirect() dari next/navigation bisa dipanggil di dalam Server Action:
// app/login/actions.ts
"use server";
import { redirect } from "next/navigation";
import { revalidatePath } from "next/cache";
export async function login(formData: FormData) {
const ok = await cekKredensial(formData);
if (!ok) {
return { error: "Email atau password salah" };
}
revalidatePath("/"); // bersihkan cache homepage (misal: tombol Login jadi Logout)
redirect("/dashboard"); // HARUS di baris terakhir
}Perilaku penting: redirect() bekerja dengan melempar error khusus yang ditangkap Next.js. Artinya kode apa pun setelahnya tidak akan pernah jalan, dan kamu tidak boleh menaruhnya di dalam try/catch yang menelan error, karena error khusus itu ikut tertelan dan redirect-nya gagal.
Satu detail yang sering membingungkan: revalidatePath tidak me-render ulang halaman secara instan di browser user yang sedang submit form. Ia hanya menandai cache sebagai basi, sehingga request berikutnya, termasuk re-render otomatis setelah Server Action selesai, mengambil data segar. Jadi alurnya: action berjalan, mutasi tersimpan, cache ditandai basi, lalu Next.js me-refresh tampilan dengan data baru. Kamu tidak perlu memanggil router.refresh() manual setelah revalidatePath di dalam action, karena refresh tampilan sudah terjadi otomatis.
Catatan teknis: Urutan yang benar selalu: mutasi, revalidate, redirect sebagai penutup. Menulis
return redirect("/x")tetap bekerja (error terlempar sebelum return dievaluasi), tapi jangan menulis kode setelahnya dengan asumsi eksekusi berlanjut normal.
Tantangan
Alur login
Buat action login dummy: bila password benar → revalidatePath("/") lalu redirect("/dashboard"); bila salah → return error yang tampil di form.