Menu

Controlled vs Uncontrolled Component di React

Input terkontrol mendapat nilainya dari state React dan hanya berubah lewat onChange. Input tidak terkontrol menyimpan nilainya sendiri di DOM, dan kamu membacanya dengan ref atau FormData. Pelajari perbedaannya, peringatan yang sering muncul, dan kapan memakai masing-masing.

Halaman ini dilengkapi editor yang bisa dijalankan. Edit, jalankan, dan lihat output-nya seketika.

Komponen terkontrol (controlled) adalah elemen form yang nilainya tinggal di state React: kamu mengirim value dan memperbarui state di onChange, jadi React yang menentukan apa yang ditampilkan input. Komponen tidak terkontrol (uncontrolled) menyimpan nilainya di DOM, seperti HTML biasa: kamu mengirim defaultValue sebagai nilai awal dan membaca nilai terkininya nanti lewat ref atau FormData.

Ketik di kedua input. Paragrafnya mengikuti input pertama di setiap ketukan tombol, karena setiap perubahan mengatur state dan merender lagi. Input kedua hanya berubah di DOM; React tidak merender, dan kamu baru melihat nilainya saat "Read both" memintanya.

Input terkontrol

Dengan input terkontrol, state React menjadi satu-satunya sumber kebenaran. Alur di setiap ketukan tombol adalah:

  1. Pengguna mengetik, dan browser memicu event input.
  2. Handler onChange milikmu membaca e.target.value dan memanggil setter.
  3. React merender lagi dan menulis state baru kembali ke value milik input.

Karena kodemu berada di tengah alur itu, kamu bisa melakukan hal yang tidak bisa dilakukan input tidak terkontrol: menolak atau mengubah bentuk karakter, menampilkan nilainya di tempat lain, menonaktifkan tombol sampai nilainya valid, atau mengatur nilainya dari kode (tombol "Clear", saran yang diklik pengguna).

Coba ketik huruf: hurufnya tidak pernah muncul, karena handler membuang semua yang bukan digit sebelum mengatur state. Tombol Verify tetap nonaktif sampai ada tepat enam digit.

Input terkontrol dipakai oleh contoh-contoh form di halaman form, dan menjadi pilihan default di sebagian besar kode React.

Input tidak terkontrol

Input tidak terkontrol bekerja seperti HTML biasa. React merendernya sekali dengan defaultValue (atau defaultChecked untuk checkbox dan radio) lalu membiarkannya. Untuk membaca nilainya, simpan ref ke elemen itu, atau baca semua field bernama dari form saat submit dengan FormData.

Tidak ada state untuk field-field itu dan tidak ada onChange. Nilainya baru dikumpulkan saat form dikirim. Hilangkan centang pada checkbox lalu kirim lagi: key subscribe menghilang, karena checkbox yang tidak dicentang sama sekali tidak termasuk dalam FormData.

Mengubah defaultValue setelah render pertama tidak berpengaruh apa pun pada input, karena React hanya menerapkannya saat elemen dibuat. Untuk mengatur ulang form tidak terkontrol, panggil e.target.reset(), atau beri form itu key baru agar React membuat input yang baru.

Input yang tidak bisa diketik

Jika kamu mengirim value tanpa onChange, input itu terkontrol, tetapi tidak ada yang pernah memperbarui state-nya. React menulis nilai yang sama kembali setelah setiap ketukan tombol, jadi input itu tampak membeku.

Coba ketik di setiap field. Field pertama tidak berubah. Field kedua adalah perbaikan untuk input terkontrol, dan saat kamu mengetik di sana, field pertama dan terakhir ikut berubah, karena ketiganya membaca state yang sama. Field ketiga menerima ketikan karena tidak terkontrol. Field keempat sengaja menyatakan bahwa ia tidak bisa diedit.

Saat development, React mencatat peringatan untuk input pertama: "You provided a value prop to a form field without an onChange handler". Pratinjau berjalan seperti build production, jadi kamu tidak akan melihat peringatan itu di sini, tetapi kamu akan melihatnya di dev server milikmu sendiri.

Berubah dari tidak terkontrol menjadi terkontrol

React menentukan apakah sebuah input terkontrol dengan melihat value. Jika value bernilai undefined atau null, input itu tidak terkontrol. Jadi input yang value-nya awalnya undefined lalu belakangan menjadi string berubah dari tidak terkontrol menjadi terkontrol selama hidupnya, dan React memberi peringatan saat development: "A component is changing an uncontrolled input to be controlled".

Peringatan itu menunjuk ke bug sungguhan. Berbalik arah, dari string ke undefined, membuat input itu tidak terkontrol lagi, dan React berhenti menulis ke input itu.

Ketik sesuatu di kedua input dan tekan setiap tombol Clear. Input kedua menjadi kosong. Input pertama tetap menyimpan teksnya: mengatur state ke undefined membuatnya tidak terkontrol, jadi React tidak lagi mengendalikan apa yang ditampilkannya.

Sumber undefined yang biasa adalah data yang belum dimuat (value={user.name} sebelum data user datang) atau field objek yang belum ada. Ada dua perbaikan:

const [name, setName] = useState('');   // start with a string
<input value={user?.name ?? ''} />       // or fall back to one

Untuk checkbox, aturan yang sama berlaku untuk checked: mulai dari false, bukan undefined.

Input file selalu tidak terkontrol

<input type="file"> tidak bisa dikontrol, karena browser tidak mengizinkan halaman mengatur nilainya (halaman yang bisa memilih file di disk-mu akan menjadi celah keamanan). Baca file yang dipilih dari e.target.files di onChange, atau lewat ref saat form dikirim.

Pilih satu atau dua file dari komputermu; tidak ada yang diunggah, contoh ini hanya menampilkan nama dan ukurannya. Satu-satunya nilai yang boleh kamu atur pada input file adalah string kosong, dan begitulah tombol Clear mengosongkannya.

Kapan memilih yang mana

TerkontrolTidak terkontrol
Nilai tinggal diState ReactDOM
Mengatur nilai awalvalue / checkeddefaultValue / defaultChecked
Membaca nilaiKapan saja, dari stateDengan ref, atau FormData saat submit
Merender di setiap ketukan tombolYaTidak
Mengubah nilai dari kodeAtur stateTulis ke DOM lewat ref
Cocok untukValidasi langsung, format, field yang saling bergantungForm sederhana yang dibaca saat submit, input file, form action

Pilih terkontrol saat layar harus merespons nilainya selama pengguna mengetik. Pilih tidak terkontrol saat kamu hanya butuh nilainya di akhir, dan begitu pula cara kerja form action di React 19: <form action={fn}> memberikan FormData ke fungsimu lalu mengatur ulang field yang tidak terkontrol sesudahnya.

Merender di setiap ketukan tombol terdengar mahal, tetapi untuk form biasa itu bukan masalah. Ini baru menjadi masalah saat tree yang besar dan lambat ikut dirender ulang bersama input itu; dalam kasus itu, simpan state dekat dengan input, atau pindahkan bagian yang lambat ke komponennya sendiri.

Dua istilah yang sama juga berlaku untuk komponen buatanmu. Komponen yang mendapat nilai dan onChange dari induknya lewat props dikontrol oleh induknya; komponen yang menyimpan state sendiri tidak terkontrol. Memindahkan state ke atas agar sebuah komponen menjadi terkontrol adalah inti dari lifting state up.

Pertanyaan yang sering diajukan

Apa itu controlled component di React?

Controlled component adalah elemen form yang nilainya saat ini berasal dari state React, diatur dengan value (atau checked) dan diperbarui lewat onChange. State React menjadi satu-satunya sumber kebenaran, jadi kamu selalu tahu nilainya dan bisa mengubahnya dari kode.

Apa itu uncontrolled component di React?

Uncontrolled component adalah elemen form yang menyimpan nilainya sendiri di DOM, seperti HTML biasa. Kamu memberinya nilai awal dengan defaultValue (atau defaultChecked) dan membaca nilainya saat dibutuhkan, lewat ref atau FormData saat submit.

Kenapa saya tidak bisa mengetik di input React saya?

Kamu mengirim value tanpa onChange. Input itu terkontrol, jadi React terus mengembalikan nilai state setelah setiap ketukan tombol. Tambahkan onChange yang memperbarui state, beralih ke defaultValue, atau tambahkan readOnly jika nilainya memang tidak boleh berubah.

Bagaimana cara memperbaiki "A component is changing an uncontrolled input to be controlled"?

value milik input itu awalnya undefined (atau null) lalu belakangan menjadi string. Pastikan nilainya selalu string: mulai state dari '', atau tulis value={name ?? ''}.

Sebaiknya saya memakai input terkontrol atau tidak terkontrol?

Pakai input terkontrol saat UI merespons nilainya selama pengguna mengetik: validasi, format, tombol yang dinonaktifkan, field yang saling bergantung. Pakai input tidak terkontrol saat kamu hanya butuh nilainya saat submit, dan untuk input file, yang selalu tidak terkontrol.

Ilustrasi bahasa pemrograman di Coddy

Belajar coding dengan Coddy

Mulai