Buat file loading.tsx di dalam folder route yang ingin menampilkan skeleton, misalnya app/dashboard/loading.tsx. Next.js App Router otomatis menampilkannya sebagai fallback saat Server Component di segmen itu mengambil data. Pola ini membuat pindah halaman terasa instan karena layout lama tetap terlihat sementara konten baru streaming.
Kesalahan yang paling sering terjadi adalah menaruh fetch data di dalam loading.tsx atau berharap file ini menangani loading untuk interaksi kecil seperti tombol dan filter.
File Loading.tsx Bekerja di App Router
Setiap folder di bawah app/ bisa punya loading.tsx sendiri. File ini membungkus page.tsx di folder yang sama dengan boundary Suspense otomatis.
- app/loading.tsx tampil untuk semua route saat navigasi awal ke segmen yang belum di-cache.
- app/dashboard/loading.tsx hanya tampil untuk /dashboard dan turunannya, layout induk tidak ikut hilang.
- Konten dikirim bertahap dengan streaming, jadi skeleton muncul dulu sebelum data selesai.
Kapan pakai loading.tsx dan kapan Suspense manual
Pakai loading.tsx untuk loading satu halaman penuh per segmen. Pakai Suspense manual bila hanya kartu, tabel, atau komentar yang lambat sementara header dan sidebar harus langsung interaktif.
Langkah Membuat Loading UI App Router
- Buat file app/dashboard/loading.tsx sebagai Server Component biasa, tanpa use client bila hanya skeleton statis.
- Tulis skeleton UI dengan Tailwind. Jangan panggil fetch, database, atau cookies di dalamnya.
export default function Loading() {
return (
<div className="space-y-4 p-6">
<div className="h-8 w-1/3 animate-pulse rounded bg-gray-200" />
<div className="h-40 animate-pulse rounded bg-gray-200" />
<div className="h-40 animate-pulse rounded bg-gray-200" />
</div>
);
}
3. Uji dengan delay sementara di page.tsx, lalu hapus setelah skeleton terlihat.
await new Promise((r) => setTimeout(r, 2000));
4. Duplikasi pola untuk nested route bila perlu, contoh app/dashboard/settings/loading.tsx dengan skeleton yang lebih kecil dan spesifik.
Perbandingan Pola Loading yang Sering Dipakai
| Pola | Kegunaan | Catatan |
|---|---|---|
| loading.tsx | Skeleton per segmen | Otomatis, Server Component |
| Suspense | Bagian kecil halaman | Kontrol granular |
| useState loading | Aksi client | Butuh use client |
Contoh Suspense untuk bagian kecil halaman:
import { Suspense } from "react";
import Stats from "./stats";
import StatsSkeleton from "./stats-skeleton";
export default function Page() {
return (
<Suspense fallback={<StatsSkeleton />}>
<Stats />
</Suspense>
);
}
- Gunakan skeleton dengan ukuran mirip konten asli agar layout tidak lompat.
- Pisahkan komponen lambat ke file sendiri supaya Suspense bisa membungkusnya.
- Hindari spinner full-screen untuk loading selevel kartu.
FAQ
Apakah loading.tsx harus Client Component?
Tidak, skeleton statis cukup sebagai Server Component tanpa use client.
Kenapa loading tidak muncul saat pindah halaman?
Umumnya halaman sudah di-cache atau fetch selesai terlalu cepat, uji dengan delay sementara.
Apakah loading.tsx bisa dipakai untuk fetch bertahap?
Tidak ideal, pecah fetch lambat ke komponen anak lalu bungkus dengan Suspense manual.