Jangan salah render! Pahami Kapan Harus Pakai `use client` dan Kapan Server Component di Next.js
Pernah enggak sih, lagi asyik ngoding Next.js dengan App Router yang baru, tiba-tiba proyek kamu error dengan pesan klasik: "ReferenceError: window is not defined," atau malah performa loading awal jadi terasa berat? Rasanya seperti lagi bikin kopi, tapi ternyata bubuk kopi yang kamu pakai itu garam. Salah render!
Dalam dunia Next.js modern, terutama sejak era App Router, kesalahan render semacam ini seringkali berakar dari ketidakpahaman fundamental tentang dua pilar utama: Server Components dan Client Components. Ini bukan sekadar masalah teknis biasa, ini adalah filosofi baru dalam membangun web yang cepat, aman, dan efisien.
Sebagai tim di balik layar di Javapixa Creative Studio, kami sering melihat developer pemula—bahkan yang sudah berpengalaman—keliru menentukan kapan harus menempelkan mantra sakti use client di bagian atas file, dan kapan harus membiarkannya berjalan secara default sebagai Server Component. Padahal, keputusan ini sangat krusial, bukan hanya untuk menghilangkan error, tapi juga untuk menjaga performa SEO dan bundle size aplikasi kamu tetap ramping.
Artikel ini akan membedah tuntas (minimal 1000 kata) semua yang perlu kamu ketahui. Kita akan menggunakan bahasa santai tapi tetap profesional, memastikan kamu bisa langsung mengaplikasikannya di proyek Next.js kamu berikutnya.
---
Next.js App Router: Paradigma Baru yang Mengubah Segalanya
Sebelum kita masuk ke perdebatan use client vs. Server Component, kita harus sepakat dulu bahwa Next.js sudah berevolusi. Di Pages Router (versi lama), semua komponen secara default diperlakukan sebagai Client Component setelah proses pre-rendering (SSR/SSG). Sekarang, dengan App Router, game rules-nya berubah total: Semua komponen adalah Server Components secara default.
Ini adalah perubahan yang masif dan revolusioner. Next.js ingin memaksimalkan kekuatan server (Node.js) untuk melakukan pekerjaan berat sebelum browser pengguna mulai memuat JavaScript.
1. Server Component (SC): Sang Juara Performa dan Keamanan
Anggaplah Server Component (SC) adalah koki utama di dapur. Mereka menyiapkan semua bahan mentah, memasak hidangan utama, dan menata piring—semua dilakukan di balik layar, jauh dari pandangan pelanggan (pengguna).
Kapan Harus Memakai Server Component (SC)?
SC adalah default yang harus kamu prioritaskan. Kalau komponen kamu tidak butuh interaksi langsung dengan pengguna atau browser, biarkan dia menjadi SC.
A. Data Fetching dan Logic Berat
SC adalah tempat terbaik untuk mengambil data. Karena SC dieksekusi di server, kamu bisa langsung:
Mengakses database (seperti Prisma, langsung dari kode komponen) tanpa perlu API endpoint* tambahan (API Layer). Mengakses file system* (misalnya membaca file Markdown). Menggunakan environment variables yang bersifat rahasia (misalnya API Key ke pihak ketiga yang tidak boleh dilihat oleh browser*).
Keuntungan Nyata: Kamu tidak perlu menunggu komponen React diunduh oleh browser untuk mulai mengambil data. Data fetching dan rendering terjadi secara bersamaan di server, mengirimkan HTML yang sudah matang ke klien.
B. Zero-Runtime Overhead
Ini adalah keuntungan terbesar. Ketika browser menerima Server Component, yang diterimanya hanyalah HTML dan CSS. Library atau package yang kamu gunakan di Server Component (misalnya date-fns untuk memformat tanggal) tidak akan pernah dimasukkan ke dalam bundle JavaScript yang harus diunduh oleh klien.
Tips Praktis: Jika kamu punya komponen yang hanya menampilkan data statis (misalnya Header, Footer, Hero Section yang datanya diambil dari CMS), pastikan itu 100% Server Component. Bundle size klien kamu akan berterima kasih.
C. Keamanan Tak Tertandingi
Karena Server Component tidak pernah dieksekusi di browser, kode sensitif yang kamu tulis di dalamnya (seperti kredensial database) sepenuhnya aman dari inspeksi pengguna.
2. Client Component (CC) dengan use client: Ketika Interaksi Wajib Ada
Jika SC adalah koki utama, maka Client Component (CC) adalah pelayan yang berinteraksi langsung dengan pelanggan (pengguna). CC bertugas mengurus permintaan interaktif dan menggunakan kemampuan browser.
Kamu wajib menaruh direktif 'use client'; di baris paling atas sebuah file komponen ketika kamu membutuhkan salah satu hal berikut:
A. Hooks Interaktif (State, Effect, dan Context)
Ini adalah pemicu yang paling jelas. Jika kamu menggunakan salah satu dari hook React berikut, komponen tersebut harus menjadi CC:
useState: Untuk mengelola keadaan (misalnya, membuka/menutup modal, menghitung jumlah like*). useEffect: Untuk menjalankan side effect setelah render (misalnya, tracking analytics, lazy loading*).
useReducer,useContext,useMemo,useCallback, dll.
B. Event Listeners (Klik, Hover, Input)
Komponen yang merespons interaksi pengguna secara langsung (seperti tombol, form input, dropdown interaktif) harus menjadi CC.
Contoh: Tombol sederhana yang mengubah warna ketika diklik atau form login yang mengelola input pengguna.
C. Akses ke Browser-Specific APIs
Server tidak tahu menahu tentang browser pengguna. Jadi, jika kamu perlu mengakses objek global seperti:
windowdocumentlocalStorage
Geolocation API*
Maka, komponen tersebut wajib menjadi CC. Jika kamu mencoba mengakses window di Server Component, kamu akan mendapatkan error "ReferenceError: window is not defined" yang terkenal itu.
---
Kesalahan Fatal yang Harus Dihindari: Batas Server dan Klien
Ini adalah bagian paling penting. Banyak developer sering melakukan kesalahan terbesar: menandai komponen besar sebagai use client padahal hanya sebagian kecil yang interaktif.
Prinsip Minimalis: Co-location (Ko-lokasi)
Tujuan utama App Router adalah meminimalkan JavaScript yang dikirim ke klien. Oleh karena itu, kamu harus membatasi area use client sekecil mungkin.
Ilustrasi Kasus:
Bayangkan kamu punya halaman Product Detail yang sangat panjang.
Skema Buruk (Anti-Pola):
jsx
// components/ProductPage.jsx
'use client'; // Seluruh halaman 1000 baris kode jadi client
import ProductData from '@/components/ProductData'; // Data statis
import BuyButton from '@/components/BuyButton'; // Hanya tombol yang interaktifexport default function ProductPage() {
// ... ribuan baris data statis
return (
{/ Seharusnya Server Component! /}
);
}Dalam skema di atas, Next.js terpaksa menjadikan seluruh ProductPage sebagai Client Component. Itu berarti semua library pendukung, semua kode, harus diunduh klien, padahal 90% isinya hanya menampilkan data statis yang sudah siap dari server.
Skema Optimal (Co-location):
- Parent Component (Server Component/Layout): Bertugas mengambil data.
- Child Component (Client Component/Button): Bertugas mengelola interaksi.
jsx
// app/product/[slug]/page.jsx (Ini adalah Server Component default)
import { fetchProduct } from '@/lib/data';
import BuyButton from '@/components/BuyButton'; // Ini adalah Client Component kecilexport default async function ProductPage({ params }) {
const product = await fetchProduct(params.slug); // Aman, Data Fetching di Serverreturn (
{product.name} {/ Server Rendered /}
{/ Server Rendered /}{/ Melewati batas: Hanya komponen tombol yang diaktifkan sebagai klien /}
);
}// components/BuyButton.jsx
'use client'; // Hanya 10 baris kode ini yang jadi Client Component
import { useState } from 'react';export default function BuyButton({ productId }) {
const [isClicked, setIsClicked] = useState(false);const handleClick = () => {
// Logic menambah ke keranjang, memerlukan state
setIsClicked(true);
};Lihat perbedaannya? Kita hanya menggunakan use client pada BuyButton—komponen terkecil yang benar-benar membutuhkan state. Konten deskripsi produk yang panjang tetap menjadi Server Component, memastikan loading cepat dan bundle size tetap minimal.
Passing Props Melalui Batas (Boundary)
Ketika Server Component me-render Client Component, SC dapat melewatkan props (properti) ke CC, selama props tersebut dapat di-serialize (diubah menjadi format yang dapat diproses, seperti string, angka, array, atau objek data sederhana).
Tips Profesional dari Javapixa:
Hindari melewatkan function atau data yang sangat kompleks yang dibuat di Server Component ke Client Component, kecuali jika kamu tahu pasti apa yang kamu lakukan (misalnya, saat menggunakan third-party context). Dalam sebagian besar kasus, lewatkan saja data mentah yang sudah di-fetch (seperti ID, nama, array data) dan biarkan Client Component menangani interaksi dengan data tersebut.
---
Checklist Cepat: Tentukan Pilihanmu!
Bingung? Gunakan checklist ini setiap kali kamu membuat komponen baru:
| Pertanyaan | Ya (Pakai use client) | Tidak (Pakai Server Component) | | :--- | :--- | :--- | | Apakah saya perlu menggunakan useState atau useEffect? | YA | TIDAK | | Apakah komponen ini berisi onClick, onChange, atau event listener lainnya? | YA | TIDAK | | Apakah saya perlu mengakses window, document, atau localStorage? | YA | TIDAK | | Apakah komponen ini digunakan untuk data fetching dari database (misalnya dengan Prisma)? | TIDAK | YA | | Apakah komponen ini hanya menampilkan data dan markup? | TIDAK | YA | | Apakah saya perlu menggunakan private environment variables? | TIDAK | YA | | Apakah saya mencoba menggunakan third-party library yang hanya berjalan di browser (misalnya library chart interaktif)? | YA | TIDAK |
Optimasi Lanjutan: Server Rendering Client Component
Meskipun komponen ditandai sebagai use client, Next.js tetap melakukan Server-Side Rendering (SSR) pada komponen tersebut pertama kali. Ini memastikan pengguna mendapatkan konten instan (untuk SEO dan performa) sebelum JavaScript diunduh dan dihidrasi (proses di mana Client Component menjadi interaktif di browser).
Penting: Jika kamu ingin mengontrol kapan Client Component di-render, kamu bisa menggunakan Suspense. Misalnya, jika kamu punya map interaktif yang butuh JavaScript besar, kamu bisa membungkusnya dengan Memuat Peta...}> di Server Component. Peta akan diunduh belakangan, sementara konten utama halaman sudah ditampilkan.
---
Javapixa Creative Studio: Partner Terbaik untuk Arsitektur Next.js
Memahami Server Component dan Client Component adalah kunci untuk membangun aplikasi modern yang sangat cepat dan scalable. Namun, implementasi di proyek skala besar—terutama yang melibatkan manajemen state kompleks, streaming, dan integrasi database yang sensitif—membutuhkan arsitektur yang kokoh.
Di Javapixa Creative Studio, kami tidak hanya sekadar menulis kode. Kami merancang arsitektur. Jika tim developer Anda merasa kesulitan memigrasikan aplikasi lama ke App Router, atau jika Anda ingin memastikan aplikasi Next.js baru Anda mencapai skor performa 100/100 di Lighthouse, kami siap menjadi partner Anda.
Kami memastikan setiap baris kode yang kami buat mengikuti prinsip co-location yang ketat, meminimalkan JavaScript klien, dan memaksimalkan keamanan yang ditawarkan oleh Server Component. Kami menjamin aplikasi yang kami bangun tidak akan mengalami error render bodoh karena salah penempatan use client.
Jangan biarkan proyek hebat Anda gagal hanya karena salah render. Percayakan arsitektur Next.js Anda kepada tim ahli Javapixa Creative Studio. Kami fokus pada performa, keamanan, dan pengalaman pengguna yang luar biasa. Hubungi kami sekarang untuk konsultasi strategi pengembangan web generasi terbaru.