Loading, Error, and Empty States
Menyusun UI data-fetching yang jujur saat data masih dimuat, gagal didapat, kosong, atau siap ditampilkan.
Tujuan belajar
- Membedakan loading, error, empty, dan ready state
- Menulis copy yang sesuai dengan kondisi data sebenarnya
- Menawarkan recovery action ketika request gagal
- Menghindari UI kosong yang menyembunyikan kondisi request
Isi lesson
6 blok- 1.Tidak ada data bukan selalu berarti data kosongBelum selesaiWajib
- 2.Satu union untuk empat keadaan daftar courseBelum selesaiWajib
- 3.Coding practiceBelum selesaiWajib
- 4.Cek pemahamanBelum selesaiWajib
- 5.Jangan menyembunyikan error sebagai layar kosongBelum selesaiWajib
- 6.RingkasanBelum selesaiWajib
Tidak ada data bukan selalu berarti data kosong
WajibSebelum request selesai, UI belum tahu apakah daftar benar-benar kosong. Jika request gagal, UI tidak boleh berpura-pura bahwa belum ada item. Karena itu, server state perlu state yang eksplisit: loading ketika data belum tersedia, error ketika request tidak berhasil, empty ketika request berhasil tetapi hasilnya kosong, dan ready ketika data dapat ditampilkan.
Setiap state perlu memberi konteks serta tindakan yang sesuai. Loading dapat menjelaskan apa yang sedang dimuat. Error perlu menyebut dampak dan menawarkan retry jika aman. Empty state perlu menjelaskan bahwa hasilnya memang belum ada, lalu memberi next action seperti mengubah filter atau membuat item pertama. Ready state menampilkan data tanpa menyembunyikan informasi penting seperti status refresh.
Bagian ini memengaruhi progres lesson.
Satu union untuk empat keadaan daftar course
Wajibtype Course = {
id: string;
title: string;
};
type CourseListState =
| { status: "loading" }
| { status: "error"; message: string }
| { status: "empty" }
| { status: "ready"; courses: Course[] };
export function CourseList({ state }: { state: CourseListState }) {
if (state.status === "loading") {
return <p aria-busy="true">Memuat course...</p>;
}
if (state.status === "error") {
return (
<section role="alert">
<p>{state.message}</p>
<button type="button">Coba lagi</button>
</section>
);
}
if (state.status === "empty") {
return <p>Belum ada course yang cocok. Coba ubah filter.</p>;
}
return (
<ul>
{state.courses.map((course) => (
<li key={course.id}>{course.title}</li>
))}
</ul>
);
}Discriminated union membuat setiap branch membawa data yang sesuai. Branch ready baru boleh membaca courses. Error memiliki copy dan action recovery; empty memberi next action yang berbeda. Button Coba lagi baru perlu dihubungkan ke request yang nyata pada local app, bukan sekadar menambahkan labelnya.
Bagian ini memengaruhi progres lesson.
Coding practice
WajibDibuka di workspace khususRender course server-state flow
Lengkapi UI daftar course untuk loading, error, empty, dan ready state yang memiliki copy serta recovery berbeda. Preview tidak menjalankan request course.
Tujuan awal: Fokus di tab TSX.
Practice ini dibuka di workspace khusus. Buka practice untuk memakai editor, preview, dan cek otomatis.
Tombol selesai aktif setelah semua validasi wajib lolos.
Cek pemahaman
WajibJawab duluCek pemahaman singkat
Kapan empty state tepat ditampilkan untuk daftar hasil pencarian?
Progres lesson naik setelah jawaban benar.
Catatan penting
WajibJangan menyembunyikan error sebagai layar kosong
Layar tanpa isi membuat user tidak tahu apakah filter terlalu sempit, data belum tersedia, atau request gagal. Berikan teks yang dapat dipahami, pertahankan filter atau input yang relevan bila aman, dan sediakan retry hanya untuk action yang benar-benar dapat dijalankan. Jangan menampilkan raw stack trace atau response internal server ke user.
Bagian ini memengaruhi progres lesson.
Ringkasan
Wajib- Loading, error, empty, dan ready adalah kondisi data yang berbeda.
- Empty hanya muncul setelah request berhasil tetapi hasil memang tidak ada.
- Error perlu context serta recovery action yang sesuai.
- Discriminated union membantu UI tidak membaca data pada state yang salah.
- Berikutnya, response API dipetakan terlebih dahulu agar component tidak bergantung pada bentuk data eksternal.
Bagian ini memengaruhi progres lesson.
Langkah berikutnya
Selesaikan bagian penting lesson ini
Lanjutkan blok wajib berikutnya: Tidak ada data bukan selalu berarti data kosong.