Biar Interaksi Tidak Error, Ini Cara Memisahkan Server dan Client Component Next Js

Cara memisahkan Server dan Client Component di Next.js App Router yang aman adalah biarkan page.tsx tetap Server Component untuk fetch data, lalu pindahkan bagian interaktif seperti tombol, form, dan player ke file kecil berlabel use client. Pola ini mencegah error onClick, useState, dan window is not defined karena kode browser tidak lagi jalan di server.

Aturan Cepat Pembagian Server dan Client Component

Anggap Server Component sebagai bawaan. Pindah ke Client Component hanya saat komponen butuh respons terhadap aksi pengguna atau API browser.

  • onClick, onChange, onSubmit wajib berada di Client Component.
  • useState, useEffect, useRef, dan custom hook berbasis state wajib di Client Component.
  • window, document, localStorage, navigator, dan Audio hanya boleh diakses dari Client Component.
  • Fetch data, akses database, dan baca cookie sensitif tetap di Server Component.
Komponen Cocok untuk Catatan batas
Judul dan artikel Render statis Tetap Server Component
Tombol tambah keranjang Interaksi klik Pindah ke use client
Form pencarian Input dan state Kirim data lewat props atau Server Action
Video player API browser Jangan render window di server

Langkah Memisahkan Server dan Client Component

1. Biarkan page dan layout tetap Server Component. Lakukan fetch data di sini agar rahasia server tidak bocor dan halaman bisa dirender statis.

2. Buat file Client Component kecil untuk bagian interaktif. Tambahkan use client di baris pertama file tombol, form, dropdown, atau player.

3. Import Client Component ke Server Component dan kirim props serializable. Kirim string, number, boolean, array, atau object polos. Jangan kirim fungsi server, objek class, atau Date mentah.

// app/produk/page.tsx
import TombolBeli from "./TombolBeli";

export default async function Page() {
  const res = await fetch("https://api.example.com/produk");
  const produk = await res.json();
  return (
    <main>
      <h1>{produk.nama}</h1>
      <TombolBeli id={produk.id} />
    </main>
  );
}

// app/produk/TombolBeli.tsx
"use client";
import { useState } from "react";

export default function TombolBeli({ id }: { id: string }) {
  const [jumlah, setJumlah] = useState(1);
  return (
    <button onClick={() => setJumlah(jumlah + 1)}>
      Beli {id}: {jumlah}
    </button>
  );
}

FAQ

Apakah semua halaman harus diberi use client?

Tidak. Beri use client hanya pada file kecil yang interaktif agar fetch tetap efisien di server.

Bolehkah import Server Component ke dalam Client Component?

Bisa lewat pola composition children atau slot, bukan import langsung komponen server yang async.

Kenapa event handler error di Server Component?

Karena handler butuh browser dan React state, jadi pindahkan kode itu ke Client Component.