Table Components
Membuat table data yang mempertahankan semantic header dan memberi context saat data dimuat atau belum tersedia.
Tujuan belajar
- Memilih table untuk data yang perlu dibandingkan per row dan column
- Menyusun caption, thead, tbody, dan th scope agar header data dapat dipahami
- Menampilkan loading dan empty state secara eksplisit
- Membuat table API yang memisahkan row data dari fetch state
Isi lesson
6 blok- 1.Gunakan table ketika hubungan antarkolom pentingBelum selesaiWajib
- 2.Table course dengan loading dan empty stateBelum selesaiWajib
- 3.Coding practiceBelum selesaiWajib
- 4.Cek pemahamanBelum selesaiWajib
- 5.Empty state adalah hasil product, bukan error visualBelum selesaiOpsional
- 6.RingkasanBelum selesaiWajib
Gunakan table ketika hubungan antarkolom penting
WajibTable tepat untuk data yang user bandingkan menurut kolom: course, status, owner, atau tanggal update. Jika setiap item lebih mirip card dengan hierarchy dan action bebas, list atau card grid lebih mudah dibaca. Memaksa semua collection menjadi table menghasilkan scroll horizontal serta header yang tidak membantu keputusan user.
Saat table tepat, header bukan dekorasi. Gunakan table, caption, thead, tbody, dan th scope. Tentukan state sebelum data ada: loading memberi tahu request sedang berjalan, empty state menjelaskan bahwa result memang tidak ada, dan error memberi recovery bila request dapat dicoba lagi. Jangan menampilkan header kosong lalu berharap user menebak apa yang terjadi.
Bagian ini memengaruhi progres lesson.
Table course dengan loading dan empty state
Wajibtype CourseRow = { id: string; title: string; status: string; updatedAt: string };
type CourseTableProps = { rows: CourseRow[]; isLoading?: boolean };
export function CourseTable({ rows, isLoading = false }: CourseTableProps) {
if (isLoading) return <p role="status">Memuat daftar course...</p>;
if (rows.length === 0) return <p>Belum ada course. Buat course pertama saat siap.</p>;
return (
<table>
<caption>Daftar course aktif</caption>
<thead><tr><th scope="col">Course</th><th scope="col">Status</th><th scope="col">Terakhir diubah</th></tr></thead>
<tbody>{rows.map((row) => <tr key={row.id}><td>{row.title}</td><td>{row.status}</td><td>{row.updatedAt}</td></tr>)}</tbody>
</table>
);
}Loading dan empty berada di luar table karena belum ada grid data yang bermakna. Setelah data tersedia, caption memberi nama table dan th scope="col" menjelaskan column. API menerima data typed serta state eksplisit; ia tidak menebak bentuk row saat render.
Bagian ini memengaruhi progres lesson.
Coding practice
WajibDibuka di workspace khususBuild course results table
Buat table course dengan loading, empty state, caption, column headers, dan typed row mapping.
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 card list lebih tepat daripada table?
Progres lesson naik setelah jawaban benar.
Tips
OpsionalEmpty state adalah hasil product, bukan error visual
Jika filter tidak menghasilkan course, empty state dapat menyebut filter aktif dan menawarkan reset. Jika account baru memang belum punya data, jelaskan langkah pertama. Jangan memakai error untuk data kosong normal atau skeleton yang terus tampil setelah request selesai.
Opsional, tidak menghambat penyelesaian lesson.
Ringkasan
Wajib- Gunakan table untuk data yang perlu dibandingkan menurut row dan column.
- Caption, thead, tbody, dan th scope menjaga struktur data dapat dipahami di luar tampilan visualnya.
- Loading, empty, dan error adalah state product dengan copy serta action berbeda.
- API table menerima row typed dan state yang eksplisit.
- Berikutnya, kita meninjau modal sebagai component yang membutuhkan focus behavior, bukan hanya overlay.
Bagian ini memengaruhi progres lesson.
Langkah berikutnya
Selesaikan bagian penting lesson ini
Lanjutkan blok wajib berikutnya: Gunakan table ketika hubungan antarkolom penting.