Semua file di folder app/ Next.js App Router otomatis menjadi Server Component. Kamu tidak perlu menambahkan kode khusus. Cukup buat file page.tsx biasa, jadikan fungsinya async, lakukan fetch langsung di dalamnya, lalu render datanya. Langkah yang sering terlewat adalah menambahkan “use client” tanpa perlu, padahal itu mematikan kemampuan fetch di server dan memperbesar bundle JS.
Cara Membuat Server Component Next Js yang Benar
Buat Server Component async untuk mengambil data sebelum halaman dikirim ke browser. Pola ini mengurangi request berantai dari client dan menjaga secret API tetap di server.
- Buat file misalnya app/products/page.tsx.
- Tulis export default async function Page() tanpa “use client”.
- Panggil fetch() atau query database langsung di dalam fungsi tersebut.
- Periksa respon dengan if (!res.ok) lalu lempar error atau tampilkan fallback.
- Render data memakai JSX biasa, lalu teruskan via props bila butuh komponen interaktif.
export default async function Page() {
const res = await fetch("https://api.example.com/products", {
next: { revalidate: 60 },
});
if (!res.ok) {
throw new Error("Gagal memuat data produk");
}
const products = await res.json();
return (
<ul>
{products.map((item: { id: string; name: string }) => (
<li key={item.id}>{item.name}</li>
))}
</ul>
);
}
Batasan Server Component dan Kapan Pakai Client
Server Component berjalan sekali di server, jadi tidak punya akses ke state browser atau event pengguna.
- Dilarang memakai useState, useEffect, useRef untuk DOM, dan context client.
- Dilarang memakai onClick, onChange, onSubmit langsung di file server.
- Dilarang membaca window, document, atau localStorage saat render.
- Pisahkan tombol, form interaktif, dropdown, modal, dan chart ke file dengan “use client”.
- Gunakan pola komposisi, yaitu Server Component memanggil Client Component sebagai anak dan mengirim data lewat props.
Tabel Perbedaan Server Component dan Client Component
| Komponen | Fungsi | Catatan |
|---|---|---|
| Server Component | Fetch data dan render statis | Bundle JS lebih kecil, bisa akses database |
| Client Component | Interaksi dan state | Dirender di server lalu dihidrasi di browser |
Contoh Kode Fetch Data dan Passing ke Client
Ambil data di page.tsx yang bersifat server, lalu kirim ke komponen produk yang interaktif. Validasi bentuk data sebelum render agar error API tidak merusak seluruh halaman.
import ProductList from "./product-list";
export default async function Page() {
const res = await fetch("https://api.example.com/products");
if (!res.ok throw new Error("Produk tidak tersedia");
const data = await res.json();
if (!Array.isArray(data)) throw new Error("Format data salah");
return <ProductList items={data} />;
}
- Jangan samakan semua fetch punya cache sama, cek opsi cache dan revalidate.
- Jangan menambahkan “use client” di halaman hanya agar fetch jalan.
- Jangan meneruskan fungsi server atau objek tak terserialisasi sebagai props ke client.
FAQ
Apakah semua file harus async?
Tidak. Jadikan async hanya komponen yang benar benar melakukan fetch atau query.
Bisakah Server Component memakai onClick?
Tidak bisa. Pindahkan onClick ke Client Component lalu kirim datanya lewat props.
Bagaimana kirim data ke Client Component?
Fetch di Server Component, lalu teruskan hasilnya sebagai props serializable seperti array atau objek polos.