Error UI
Menangani error per-segmen dengan error.tsx dan tombol reset.
Error tidak harus meruntuhkan seluruh halaman
Di aplikasi React biasa, error saat render sering meruntuhkan seluruh aplikasi menjadi layar putih. Next.js App Router punya pendekatan lebih halus: file error.tsx menangkap error hanya di segmennya, sehingga sidebar, header, dan halaman lain tetap hidup normal.
Ini adalah konsep Error Boundary yang dibungkus menjadi konvensi file, sama seperti loading.tsx untuk loading dan not-found.tsx untuk 404.
Contoh 1: error.tsx dasar dengan tombol reset
// app/blog/error.tsx
"use client";
import { useEffect } from "react";
export default function Error({
error,
reset,
}: {
error: Error & { digest?: string };
reset: () => void;
}) {
useEffect(() => {
console.error("Blog error:", error);
}, [error]);
return (
<div className="rounded border p-8 text-center">
<h2>Gagal memuat blog</h2>
<p>{error.message}</p>
<button onClick={reset}>Coba lagi</button>
</div>
);
}Tiga aturan penting:
- Wajib
"use client"di baris pertama. Error boundary butuh interaktivitas (tombol reset, logging error), dan boundary hanya bisa berupa Client Component. - Menerima dua props:
error(object Error yang tertangkap, plusdigestopsional untuk pelacakan) danreset(fungsi untuk mencoba me-render ulang segmen tanpa reload halaman). - Logging error lewat
useEffectadalah pola resmi: catat error ke layanan monitoring di sini, jangan lakukan side effect langsung saat render.
Contoh 2: memicu error dan melihat isolasinya
Error boundary paling terasa manfaatnya saat satu section gagal tapi sisanya selamat:
// app/blog/page.tsx
export default async function BlogPage({
searchParams,
}: {
searchParams: Promise<{ gagal?: string }>;
}) {
const params = await searchParams;
if (params.gagal) {
throw new Error("Simulasi kegagalan database");
}
return <h1>Daftar artikel</h1>;
}app/
├── layout.tsx # header/footer global: tetap tampil saat blog error
└── blog/
├── error.tsx # hanya menangkap error di dalam /blog
└── page.tsx
Buka /blog?gagal=1 dan hanya area blog yang digantikan UI error, header dan footer dari root layout tetap tampil normal. Klik "Coba lagi" dan Next.js mencoba me-render ulang segmen blog tanpa me-reload seluruh halaman. Buka /blog tanpa param dan semuanya normal kembali.
Batasan yang wajib diketahui
- Error di root layout tidak bisa ditangkap
error.tsxbiasa, karena boundary-nya sendiri berada di dalam layout yang sedang error. Untuk itu pakaiglobal-error.tsx(modul terpisah) yang wajib me-render<html>dan<body>sendiri. error.tsxhanya menangkap error saat rendering dan data fetching di Server Component maupun Client Component dalam segmennya. Error di event handler (misalnya di dalamonClick) tidak tertangkap, untuk itu tetap pakai try/catch manual.notFound()bukan error dan tidak ditangkaperror.tsx, ia me-rendernot-found.tsxseperti yang dibahas di modul navigasi programmatic. Jangan campuradukkan keduanya.
Ringkasan:
error.tsxadalah Error Boundary per segmen yang wajib Client Component, menerima propserrordanreset, dan mengisolasi kegagalan supaya tidak merembet ke seluruh aplikasi. Pasangkan dengan logging error yang benar danglobal-error.tsxuntuk perlindungan berlapis dari level section sampai level aplikasi.
Tantangan
Simulasi error
Buat halaman yang melempar error bila query param ?gagal=1 ada, plus error.tsx dengan tombol reset. Buka URL dengan dan tanpa param, amati bedanya.