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 Componentsmuncul di terminal. onClicktidak merespons karena tidak ada JavaScript client yang terpasang.- Kode
window,document, ataulocalStoragegagal 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.
- Buat file
Counter.tsxdengan baris pertama"use client". - Pindahkan
useStatedanonClickke file tersebut. - Import
Counterdaripage.tsxyang 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.