- Bab 5 dari 10
- 30 menit
- 1 latihan kode
- 4 soal kuis
Event dan useState: membuat komponen bereaksi
Di bab ini (10 bagian)
Tujuan bab ini
- Menangani event pengguna dengan
onClick,onChange, danonSubmit, serta paham kenapa yang dioper adalah fungsi, bukan hasil pemanggilannya. - Menyimpan data yang berubah dengan
useStatedan memperbaruinya lewat fungsi set. - Memperbarui state berdasarkan nilai sebelumnya dengan
setX(prev => ...), termasuk state berupa object dan array secara immutable. - Memahami kenapa perubahan state memicu render ulang dan apa itu batching.
Event di React: mirip HTML, beda sedikit
Di HTML biasa kamu mungkin pernah menulis <button onclick="simpan()">. Di React, aturannya sedikit berbeda:
- Nama event ditulis camelCase:
onClick,onChange,onSubmit,onKeyDown,onMouseEnter. - Nilainya adalah fungsi di dalam kurung kurawal, bukan string.
Parameter e adalah objek event. Dua properti yang paling sering kamu pakai: e.target.value untuk membaca isi input, dan e.preventDefault() untuk mencegah perilaku bawaan browser, misalnya form yang otomatis mengirim dan me-reload halaman.
| Event | Kapan terpicu | Contoh pemakaian |
|---|---|---|
onClick | Elemen diklik | Tombol tambah, hapus, buka menu |
onChange | Isi input, textarea, atau select berubah | Kolom pencarian, form daftar |
onSubmit | Form dikirim (klik tombol submit atau Enter) | Login, kirim komentar |
onKeyDown | Tombol keyboard ditekan | Shortcut, tutup modal dengan Escape |
onMouseEnter | Kursor masuk ke area elemen | Tooltip, efek hover |
Catatan kecil: di React, onChange pada input terpicu setiap ketikan, bukan hanya saat input kehilangan fokus seperti event change di HTML biasa.
Oper fungsinya, jangan panggil
Ini kesalahan nomor satu pemula. Bandingkan:
Analoginya begini: onClick={sapa} itu seperti memberi nomor HP temanmu ke satpam, "telepon dia kalau ada tamu". Sedangkan onClick={sapa()} itu kamu langsung menelepon temanmu saat itu juga, lalu memberikan hasil teleponnya ke satpam. React mengevaluasi semua yang ada di dalam {} saat render, jadi sapa() jalan setiap kali komponen dirender, bukan saat diklik. Kalau di dalam sapa ada fungsi set state, hasilnya bisa render tanpa henti dan React menampilkan error "Too many re-renders".
State dengan useState
Variabel biasa di dalam komponen tidak cukup untuk data yang berubah. Coba ini:
Ada dua masalah: React tidak tahu bahwa angka berubah, jadi tidak merender ulang; dan setiap kali fungsi komponen dipanggil lagi, let angka = 0 mulai dari nol lagi. Solusinya adalah state, yaitu data milik komponen yang diingat React di antara render.
Langkah-langkahnya:
- Deklarasi:
useState(0)membuat state dengan nilai awal0. Hasilnya array berisi dua hal, yang kita ambil dengan destructuring: nilai saat ini (angka) dan fungsi pengubah (setAngka). - Pemakaian: tampilkan
angkadi JSX seperti variabel biasa. - Pembaruan: panggil
setAngka(nilaiBaru). Jangan pernahangka++atauangka = 5, karena React tidak akan tahu ada perubahan.
Bedakan dengan props: props datang dari komponen induk dan bersifat read-only, sedangkan state milik komponen itu sendiri dan boleh diubah lewat fungsi set.
Kenapa set state memicu render ulang
Saat kamu memanggil setAngka(1), React menyimpan nilai baru lalu memanggil ulang fungsi komponenmu. Kali ini useState mengembalikan 1, JSX yang dihasilkan berisi "Jumlah klik: 1", dan React hanya memperbarui bagian DOM yang berbeda. Jadi tampilan selalu hasil dari data: UI = f(state).
Konsekuensi penting: di dalam satu render, nilai angka itu seperti foto. Memanggil setAngka tidak mengubah variabel angka yang sedang kamu pegang, nilai baru baru terlihat di render berikutnya.
React juga membandingkan nilai baru dengan yang lama memakai Object.is. Kalau sama persis, React boleh melewati render ulang.
Update berdasar nilai sebelumnya
Bagaimana kalau kamu memanggil set tiga kali berturut-turut?
Ketiganya membaca foto yang sama, yaitu angka = 0. Solusinya adalah updater function: oper fungsi yang menerima nilai sebelumnya.
React menaruh fungsi-fungsi ini di antrean lalu menjalankannya berurutan, masing-masing menerima hasil dari yang sebelumnya. Kebiasaan yang bagus: kalau nilai baru bergantung pada nilai lama, pakai bentuk prev => ....
Batching: banyak set, satu render
Pada contoh di atas, apakah komponen dirender tiga kali? Tidak. React mengumpulkan semua pembaruan state dalam satu event handler, lalu merender sekali setelah handler selesai. Ini disebut batching. Analoginya pelayan restoran yang mencatat semua pesananmu dulu, baru ke dapur sekali jalan, bukan bolak-balik untuk setiap menu. Sejak React 18, batching otomatis berlaku juga di dalam setTimeout, promise, dan event lain, tidak hanya di event handler React.
State object dan array: immutable
State boleh berupa object atau array, tapi kamu harus memperlakukannya sebagai read-only. Jangan ubah isinya langsung, buat salinan baru.
Untuk array, pakai method yang menghasilkan array baru:
| Tujuan | Hindari (mutasi) | Pakai (immutable) |
|---|---|---|
| Menambah | push, unshift | [...arr, item], [item, ...arr] |
| Menghapus | splice | arr.filter((x) => x.id !== id) |
| Mengubah satu item | arr[i] = ... | arr.map((x) => x.id === id ? { ...x, selesai: true } : x) |
| Mengurutkan | sort langsung | [...arr].sort(...) atau toSorted(...) |
Kenapa harus begini? Karena React mendeteksi perubahan dengan membandingkan referensi. Object baru berarti referensi baru, dan React tahu harus merender ulang.
Kesalahan umum
onClick={fungsi()}: fungsi jalan saat render. TulisonClick={fungsi}atauonClick={() => fungsi(arg)}.- Mengubah state langsung (
angka++,arr.push(x),obj.a = 1): tampilan tidak ikut berubah. Selalu lewat fungsi set dengan nilai baru. - Membaca state tepat setelah set dan berharap nilainya sudah baru. Nilai baru baru muncul di render berikutnya.
- Lupa
e.preventDefault()dionSubmit: halaman ter-reload dan state hilang. - Spread yang dangkal:
{ ...prev }hanya menyalin satu level. Object di dalam object juga perlu di-spread.
Rangkuman
- Event React ditulis camelCase dan menerima fungsi. Oper referensinya atau bungkus dengan arrow function, jangan panggil langsung.
useState(awal)mengembalikan[nilai, setNilai]. Memanggil set menyimpan nilai baru dan membuat React merender ulang komponen.- Di dalam satu render, state seperti foto. Pakai
setX(prev => ...)bila nilai baru bergantung pada nilai lama. - React melakukan batching: banyak set dalam satu event menghasilkan satu render.
- Object dan array di state diperbarui secara immutable dengan spread,
map, danfilter.
Slide 20 sampai 22 dari deck ReactJS. Penjelasan lengkapnya ada di mode Baca.

Selesaikan bab ini
- 1. Baca materi
- 2. Latihan kode (1)
- 3. Kuis (4 soal)
Latihan kode: Update daftar tugas secara immutable
Di komponen daftar tugas, state-nya berupa array seperti [{ id: 1, judul: "Belajar JSX", selesai: false }]. Setiap aksi dipanggil lewat updater, misalnya setTugas(prev => tambahTugas(prev, 3, "Ngoding")).
Lengkapi fungsi murni berikut. Jangan ubah array atau object asli, selalu kembalikan yang baru:
tambahTugas(list, id, judul)menambah{ id, judul, selesai: false }di akhir.toggleTugas(list, id)membalikselesaipada tugas denganiditu, tugas lain tetap object yang sama.hapusTugas(list, id)membuang tugas denganiditu.sisaTugas(list)mengembalikan jumlah tugas yang belum selesai (dipakai untuk teks "3 tugas tersisa").
Petunjuk: spread, map, filter.
Cek pemahaman
1Tombol di bawah diklik satu kali (awalnya n = 0). Angka berapa yang tampil setelah render ulang?
function Penghitung() { const [n, setN] = useState(0); function klik() { setN(n + 1); setN(n + 1); setN((prev) => prev + 1); } return <button onClick={klik}>{n}</button>; }2Apa akibat menulis <button onClick={hapus()}>Hapus</button>?
3Menjalankan daftar.push(item) lalu setDaftar(daftar) adalah cara yang benar untuk menambah item ke state array.
4Sebuah event handler memanggil tiga fungsi set state berbeda berturut-turut. Berapa kali komponen dirender ulang?