nextjsrscrenderingMenengah5 mnt baca

Server vs Client Component

Memahami dua jenis komponen: di mana render dan apa bedanya.

Dua dapur dalam satu restoran

Bayangkan restoran dengan dua dapur. Dapur utama (server) punya akses ke gudang bahan, resep rahasia, dan kompor industri: semua masakan berat dikerjakan di sana, lalu hidangan jadi diantar ke meja. Dapur kecil di meja tamu (client) hanya untuk hal yang harus dilakukan di depan tamu: memotong buah segar atau menyalakan lilin.

Server Component dan Client Component bekerja dengan pembagian seperti itu. Server Component "memasak" di server: mengambil data dari database, membaca API key rahasia, me-render HTML jadi, lalu mengirim hasilnya ke browser. Client Component "diselesaikan" di browser agar bisa interaktif: merespons klik, menyimpan state, membaca localStorage.

Kenapa pembagian ini ada

Di era React lama, SEMUA komponen dikirim sebagai JavaScript ke browser, lalu browser me-render semuanya. Akibatnya: bundle besar, halaman lambat di HP kentang, dan data sensitif gampang bocor karena kodenya terlihat di DevTools.

Next.js App Router membalik defaultnya: semua komponen adalah Server Component kecuali kamu menandainya "use client". Hasilnya: JavaScript yang dikirim ke browser jauh lebih sedikit, data rahasia tetap di server, dan halaman terasa cepat.

Contoh 1: halaman server + pulau interaktif

tsx
// app/page.tsx (Server Component, default, tanpa "use client")
import { db } from "@/lib/db";
import LikeButton from "./LikeButton";

export default async function HomePage() {
  const posts = await db.post.findMany({ take: 10 }); // aman: query di server

  return (
    <main>
      <h1>Artikel terbaru</h1>
      <ul>
        {posts.map((p) => (
          <li key={p.id}>
            {p.title} <LikeButton postId={p.id} />
          </li>
        ))}
      </ul>
    </main>
  );
}
tsx
// app/LikeButton.tsx
"use client";

import { useState } from "react";

export default function LikeButton({ postId }: { postId: string }) {
  const [liked, setLiked] = useState(false);
  return (
    <button onClick={() => setLiked(!liked)} aria-pressed={liked}>
      {liked ? "❤️" : "🤍"} Suka
    </button>
  );
}

Daftar artikel di-render di server (cepat, SEO-friendly, tanpa JS), hanya tombol like yang dikirim JavaScript-nya ke browser. Pola "pulau interaktif di lautan konten statis" ini adalah pola paling umum di App Router. Perhatikan props yang dikirim ke Client Component (postId, string) sederhana dan serializable.

Contoh 2: butuh API browser? wajib client

tsx
// app/WidthInfo.tsx
"use client";

import { useEffect, useState } from "react";

export default function WidthInfo() {
  const [width, setWidth] = useState(0);

  useEffect(() => {
    const update = () => setWidth(window.innerWidth); // window hanya ada di browser
    update();
    window.addEventListener("resize", update);
    return () => window.removeEventListener("resize", update);
  }, []);

  return <p>Lebar layar saat ini: {width}px</p>;
}

window, document, localStorage, dan navigator tidak ada di server. Kode yang menyentuhnya harus tinggal di Client Component. Kalau kamu memaksa memakainya di Server Component, dapat error window is not defined saat render.

Tabel keputusan cepat

KebutuhanPilih
Fetch data / query databaseServer
Membaca API key atau secretServer
Menampilkan daftar konten statisServer
useState, useEffect, event handlerClient
Browser API (window, localStorage)Client
Library pihak ketiga yang interaktifClient (dibungkus tipis)

Satu kesalahpahaman yang paling sering ditemui: "use client" BUKAN berarti "hanya di-render di client". Komponen client tetap di-prerender di server menjadi HTML awal, lalu "dihidupkan" di browser lewat proses bernama hydrasi. Arti tepat "use client" adalah: komponen ini boleh memakai fitur client, dan JavaScript-nya akan dikirim ke browser. Jadi jangan panik kalau komponen client tetap muncul di HTML awal, itu memang disengaja demi kecepatan tampil pertama.

Tantangan

Klasifikasi

Klasifikasikan 5 kebutuhan ini ke Server/Client: (a) baca database, (b) tombol like, (c) baca localStorage, (d) tampilkan daftar produk, (e) validasi form realtime.