Solusi Praktis Cara Mengatasi useState Tidak Bisa di Server Component

Pindahkan useState ke file terpisah yang diawali "use client", lalu import file itu dari Server Component. Default semua file di App Router adalah Server Component, jadi React menolak hook seperti useState, useEffect, serta event seperti onClick kalau ditulis langsung di page.tsx.

Kenapa useState Menolak Jalan di Server Component

Server Component dirender di server untuk mengambil data dan menghasilkan HTML. Ia tidak menyimpan state antar klik dan tidak menjalankan lifecycle client.

Pola yang benar: page tetap server untuk fetch data, bagian interaktif dibungkus Client Component kecil.

  • Pesan React hooks cannot be used in Server Components muncul di terminal.
  • onClick tidak merespons karena tidak ada JavaScript client yang terpasang.
  • Kode window, document, atau localStorage gagal saat render server.

Tabel Troubleshooting Error useState di App Router

Masalah Penyebab Solusi
Hook error di page useState ditulis di Server Component Pindah ke file dengan use client
Event handler mati Tidak ada boundary client Bungkus tombol di Client Component
Hydration mismatch Render server dan client beda Hindari Date acak dan browser API saat render awal

Baca log terminal dulu, bukan hanya overlay browser. Nama file dan baris di stack React biasanya menunjuk langsung ke komponen yang lupa diberi "use client".

Solusi Memindahkan State ke Client Component Terpisah

Isolasi state sekecil mungkin. Jangan ubah seluruh page menjadi client kalau hanya satu tombol yang butuh useState.

  1. Buat file Counter.tsx dengan baris pertama "use client".
  2. Pindahkan useState dan onClick ke file tersebut.
  3. Import Counter dari page.tsx yang tetap server.
// app/Counter.tsx
"use client";
import { useState } from "react";

export default function Counter() {
  const [count, setCount] = useState(0);
  return <button onClick={() => setCount(count + 1)}>Klik: {count}</button>;
}

// app/page.tsx
import Counter from "./Counter";

export default function Page() {
  return (
    <main>
      <h1>Data Server</h1>
      <Counter />
    </main>
  );
}
  • Tetap server: fetch data, metadata, query database, Tampilkan konten statis.
  • Wajib client: input form, toggle menu, tab, modal, counter, validasi instan.
  • Props dari server ke client harus serializable, hindari oper fungsi server.

FAQ

Apakah semua page harus diberi use client agar useState bisa dipakai?

Tidak. Cukup komponen terkecil yang butuh state yang diberi "use client".

Bolehkah fetch data server lalu oper ke Client Component berisi useState?

Boleh. Ini pola resmi: fetch di Server Component, kirim hasilnya sebagai props.

Bagaimana mengatasi window is not defined setelah pindah ke Client Component?

Akses window di dalam useEffect atau pengecekan event handler, bukan saat render awal.