Tanpa event handler, web kamu cuma "foto statis" — bisa diliat tapi gak bisa direspon. Klik tombol = gak ada apa-apa. Ketik di input = tetap kosong. Hover di kartu produk = no animation. Event handler yang ngubah aplikasi pasif jadi interaktif. Di React, handle event mirip HTML — tapi dengan camelCase (onClick, bukan onclick) dan kasih fungsi sebagai handler (bukan string JS).
function App() {
const handleClick = () => {
console.log("Tombol diklik!")
}
return <button onClick={handleClick}>Klik Saya</button>
}
💡 WAJIB inget — pass FUNCTION, bukan CALL.
<button onClick={handleClick}>✓ (pass function reference).<button onClick={handleClick()}>✗ (CALL function langsung pas render — handler jalan otomatis tiap re-render, infinite loop disaster). Bug paling sering pemula.
Event Object
Tiap event handler otomatis terima objek event sebagai argumen:
function App() {
const handleChange = (e) => {
console.log(e.target.value) // nilai input saat ini
}
return <input onChange={handleChange} />
}
Common properties di event object:
e.target— elemen yang trigger evente.target.value— nilai input (untuk form)e.preventDefault()— cegah default browser action (form submit reload, link navigate)e.stopPropagation()— stop event bubbling ke parent
Pass Argument ke Handler
// ❌ SALAH — call langsung pas render
<button onClick={deleteItem(id)}>Hapus</button>
// ✓ BENAR — bungkus dalam arrow function
<button onClick={() => deleteItem(id)}>Hapus</button>
// ✓ ALTERNATIF — jika handler simpel banget
<button onClick={handleClick} data-id={id}>Hapus</button>
// Lalu di handler: e.target.dataset.id
Event Umum
| Event | Trigger |
|---|---|
onClick |
Elemen diklik |
onChange |
Nilai input berubah |
onInput |
User ketik (sebelum onChange) |
onSubmit |
Form di-submit |
onKeyDown / onKeyUp |
Keyboard ditekan/dilepas |
onMouseEnter / onMouseLeave |
Mouse masuk/keluar |
onFocus / onBlur |
Input fokus/lepas fokus |
onScroll |
Element/window di-scroll |
🎭 Analogi sehari-hari
Event handler itu kayak bel di pintu rumah. Pas tamu pencet bel (event "click"), aksi tertentu trigger — speaker bunyi, kamera nyala, notif ke HP. Kamu (developer) yang nentuin aksi apa pas bel ditekan. Pasang fungsi handleClick sama kayak install peralatan ke bel: "kalo bel pencet, jalankan instruksi ini". Pemula sering salah cabang kabel — onClick={handleClick()} itu kayak "pas mau install bel, langsung pencet bel-nya" (call langsung). Bel berbunyi infinite loop, RUSAK. Yang bener install dulu: onClick={handleClick} — pass referensi, baru bel berbunyi pas tamu beneran pencet.
⚠️ Jebakan yang sering ditemui
onClick={handleClick()}= call langsung, infinite loop. Hapus().- camelCase wajib —
onclick(HTML) gak jalan, harusonClick(React). - Lupa
e.preventDefault()di form — submit form = browser reload halaman default. WAJIB cegah biar SPA jalan. - Inline arrow di setiap render —
onClick={() => doStuff()}create function baru tiap render. Performa OK buat handler simple, tapi bermasalah pas pass keReact.memochild (memo gagal). PakaiuseCallback. - Lupa pass event —
function handleChange() { console.log(e.target.value) }—eundefined. Tambah parameter:(e) => .... - Async handler tanpa try/catch — error async gak ke-catch ErrorBoundary. Wrap manual.
- Event bubbling — klik tombol di dalam card,
onClickcard juga trigger. Stop dengane.stopPropagation()di tombol. onChangetext input behavior — di ReactonChangejalan TIAP keystroke (kayakonInputdi vanilla), beda dari HTML standard. Confuse pas pindah dari vanilla.
🎯 Pass argument ke handler — gimana caranya?
- Static value → bungkus arrow:
onClick={() => deleteItem(123)}- Item dalam list → arrow di map:
items.map(item => <Item onDelete={() => deleteItem(item.id)} />)- Banyak item, perf concern → pakai data attribute:
<button data-id={id} onClick={handleClick}>lalue.target.dataset.id- Pre-bind di handler →
handleClick = (id) => () => deleteItem(id)(curry, advanced)Default: arrow inline. Optimisasi cuma pas profiler nunjukin masalah.
TL;DR: Event handler di React = pass FUNCTION (gak CALL!) ke prop event camelCase (onClick, onChange). Handler nerima e (event object) — e.target.value buat input, e.preventDefault() buat cegah default. Pass arg ke handler? Bungkus arrow () => fn(arg). Form submit WAJIB e.preventDefault() biar gak reload. onChange di input jalan tiap keystroke (beda dari HTML standard).