nextjsserver-actionscacheMenengah3 mnt baca

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:

tsx
// 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:

tsx
// 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:

tsx
// 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.