Cara menggunakan event handler Next.js yang benar adalah menaruh onClick, onChange, dan onSubmit di Client Component dengan "use client" di baris pertama. Server Component tidak bisa menyimpan fungsi klik karena kodenya jalan di server dan tidak punya akses ke browser. Pola praktisnya: halaman tetap Server Component, lalu buat komponen tombol atau form kecil yang client khusus untuk interaksi.
Jawaban Cepat: onClick dan onChange Hanya Jalan di Client
Event handler React butuh browser. Itu sebabnya file yang berisi onClick wajib diawali "use client".
"use client";
export default function TombolSimpan() {
function handleKlik() {
alert("Tersimpan di browser");
}
return <button onClick={handleKlik}>Simpan</button>;
}
Bedakan dua jenis handler di App Router. Handler browser seperti onClick berjalan di client untuk UI. Server Action berjalan di server untuk tulis database atau validasi sensitif.
Aturan Server Component untuk Event Handler
File app/page.tsx tanpa "use client" adalah Server Component. Menaruh onClick={() => ...} di sana memicu error karena fungsi tidak bisa diserialisasi ke client.
Solusinya bukan mengubah semua halaman jadi client. Pisahkan bagian interaktif ke file kecil, lalu impor dari Server Component.
onClick,onChange,onBlurwajib di Client Component.onSubmitform interaktif juga butuh client bila memakai state ataupreventDefault.- Akses
window,document, danlocalStoragehanya aman di event atauuseEffectclient.
Langkah Praktis Pasang Event di App Router
- Buat file baru untuk UI interaktif, contoh
app/Tombol.tsx, lalu tulis"use client"paling atas. - Tulis handler dengan
eventbila butuh nilai input atau cegah reload form. - Impor komponen client itu dari
page.tsxServer Component dan teruskan data lewat props.
"use client";
import { useState } from "react";
export function FormNama({ onSimpan }: { onSimpan: (nama: string) => void }) {
const [nama, setNama] = useState("");
return (
<form
onSubmit={(e) => {
e.preventDefault();
onSimpan(nama);
}}
>
<input value={nama} onChange={(e) => setNama(e.target.value)} />
<button type="submit">Kirim</button>
</form>
);
}
Untuk simpan ke database, teruskan Server Action lewat props atau pakai atribut action pada form. Validasi ulang di server tetap wajib walau client sudah cek input.
Tabel Kesalahan Umum dan Perbaikannya
| Masalah | Penyebab | Solusi |
|---|---|---|
| Handler tidak jalan | Tombol ada di Server Component | Pindah tombol ke file "use client" |
| Hydration error | State awal beda server dan client | Samakan nilai awal, baca waktu atau storage di useEffect |
window is not defined |
Browser API dipanggil saat render server | Panggil di dalam handler atau useEffect |
FAQ
Apakah semua halaman harus use client?
Tidak. Biarkan halaman server, hanya komponen tombol dan form yang client.
Bisakah event handler memanggil Server Action?
Bisa. Impor Server Action lalu panggil dari handler client, dengan validasi input di server.
Kapan pakai Route Handler bukan onClick biasa?
Pakai Route Handler untuk API GET, POST, webhook, atau upload yang butuh respons HTTP eksplisit.