Menu

Form React: Input, Checkbox, Select, dan Validasi

Buat form di React dengan input terkontrol: field teks, textarea, select, checkbox, dan radio button, satu objek state untuk banyak field, submit dengan onSubmit, menampilkan error validasi, dan form action di React 19.

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

Form React menyimpan nilai setiap field di state: input menampilkan value={state} dan memperbaruinya dengan onChange. Saat pengguna mengirim form, handler onSubmit memanggil e.preventDefault() untuk mencegah halaman dimuat ulang, lalu memakai nilai yang sudah ada di state.

Ketik sebuah nama lalu tekan Enter atau klik tombolnya. Kemudian hapus baris e.preventDefault();: pratinjau menampilkan field yang akan dikirim browser dalam pengiriman form bawaan, yang di halaman sungguhan juga akan memuat ulang halaman.

Input yang nilainya berasal dari state disebut input terkontrol. Alternatifnya, membiarkan DOM menyimpan nilainya lalu membacanya nanti, dibahas di controlled vs uncontrolled component.

Input teks dan textarea

Setiap field teks bekerja dengan cara yang sama: value dari state, onChange membaca e.target.value. <textarea> mengikuti pola yang sama. Di HTML, teksnya ditaruh di antara tag, tetapi di React kamu mengirimnya sebagai value.

Karena kamu sendiri yang mengatur nilainya, kamu bisa mengubah apa yang diketik pengguna sebelum ditampilkan: field judul mengubah setiap huruf menjadi kapital. Penghitung karakter diperbarui di setiap ketukan tombol karena body adalah state dan setiap perubahan memicu render lagi.

Select

<select> menerima value di elemen select itu sendiri, bukan selected di sebuah option. e.target.value adalah value dari option yang dipilih.

Untuk select dengan banyak pilihan, tambahkan multiple dan kirim array sebagai value. Baca pilihannya dengan Array.from(e.target.selectedOptions, (o) => o.value).

Checkbox dan radio button

Checkbox dikontrol dengan checked, bukan value, dan handler-nya membaca e.target.checked, yang bernilai true atau false. Radio button dalam satu grup memakai name yang sama; masing-masing tercentang saat state sama dengan nilainya.

Membaca e.target.value pada checkbox adalah kesalahan yang umum: untuk checkbox tanpa atribut value, hasilnya adalah string "on", entah kotaknya dicentang atau tidak.

Satu objek state untuk banyak field

Form dengan sepuluh field tidak butuh sepuluh pemanggilan useState dan sepuluh handler. Simpan satu objek, beri setiap input name yang sesuai dengan sebuah key, lalu tulis satu handler yang memakai name itu sebagai key hasil perhitungan: [e.target.name].

Handler-nya memeriksa tipe input sehingga checkbox menyimpan boolean dan field lainnya menyimpan teks. Tambahkan sebuah field dengan menambahkan key ke objek awal dan input dengan name yang sama; handler-nya tidak perlu diubah. Spread mempertahankan semua field lainnya (lihat memperbarui array dan objek).

Mengirim form

Taruh logika submit di onSubmit milik form, bukan di onClick milik tombol. onSubmit juga terpicu saat pengguna menekan Enter di field teks, sesuatu yang akan terlewat oleh handler klik. <button> di dalam form secara default adalah tombol submit; beri tombol lain type="button" agar tidak mengirim form.

Buka konsol, ketik sebuah password, lalu tekan Enter: form mencatat seluruh objeknya. Mengklik "Clear" tidak mencatat apa pun, karena tombol itu type="button". Hapus atribut itu, dan Clear juga ikut mengirim form.

Validasi dan menampilkan error

Validasi sederhana adalah fungsi yang menerima nilai-nilai form dan mengembalikan objek berisi pesan. Jalankan saat submit, simpan hasilnya di state, dan tampilkan setiap pesan di bawah field-nya. Nonaktifkan tombol submit selama request berjalan agar klik ganda tidak mengirim form dua kali.

Klik Save dengan field kosong untuk melihat kedua pesan, lalu isi field-nya. saveProfile adalah pengganti request sungguhan: ia menunggu 800 milidetik lalu selesai. Atribut noValidate mematikan gelembung validasi bawaan browser sehingga hanya pesanmu yang tampil; hapus atribut itu dan tambahkan required ke sebuah input untuk membandingkannya.

Error juga bisa dihitung saat render alih-alih disimpan, misalnya const emailError = form.email && !form.email.includes('@'), yang menampilkan pesan selagi pengguna mengetik. Pilih waktu yang cocok untuk form-nya: saat submit terasa lebih tenang, sedangkan saat mengetik memberi umpan balik lebih cepat.

Form action di React 19

React 19 menambahkan cara lain untuk menangani form. Kirim fungsi ke prop action milik form. React mencegah halaman dimuat ulang untukmu dan memanggil fungsi itu dengan objek FormData yang berisi setiap field yang punya name. Field-field itu sama sekali tidak butuh state: semuanya tidak terkontrol, dan React mengosongkannya setelah action selesai.

Ketik komentarmu sendiri lalu kirim. List menampilkan teksmu, dan input kembali ke Nice docs: setelah action selesai, React mengembalikan field yang tidak terkontrol ke defaultValue-nya. Action bisa berupa fungsi async, dan selama berjalan, React memperlakukan pembaruannya sebagai transition.

Untuk menampilkan keadaan pending atau error dari action, bungkus dengan useActionState, yang mengembalikan hasil terbaru, action yang sudah dibungkus untuk form, dan flag isPending. Tombol yang berada jauh di dalam form juga bisa membaca keadaan pending dengan useFormStatus dari react-dom:

import { useFormStatus } from 'react-dom';

function SubmitButton() {
    const { pending } = useFormStatus();
    return <button disabled={pending}>{pending ? 'Posting...' : 'Post'}</button>;
}

useFormStatus tidak dimuat di editor di sini, jadi ia hanya muncul di blok statis ini. Hook ini harus dipanggil dari komponen yang dirender di dalam <form>, bukan di komponen yang merender form-nya.

State terkontrol dengan onSubmit dan form action dengan FormData sama-sama berjalan di React 19. Field terkontrol cocok untuk form yang merespons selagi kamu mengetik (validasi langsung, penghitung karakter, field yang saling bergantung). Action cocok untuk form yang nilainya hanya kamu butuhkan saat pengguna mengirimnya.

Pertanyaan yang sering diajukan

Bagaimana cara mendapatkan nilai input di React?

Simpan di state dan perbarui dari onChange: <input value={name} onChange={e => setName(e.target.value)} />. Teks terkininya pun selalu ada di name. Untuk checkbox, baca e.target.checked, bukan e.target.value.

Bagaimana cara mencegah form memuat ulang halaman di React?

Panggil e.preventDefault() di awal handler onSubmit. Tanpanya, browser melakukan pengiriman form biasa, yang berpindah halaman dan memuat ulang halaman.

Bagaimana cara menangani banyak input dengan satu state di React?

Simpan satu objek di state, beri setiap input name yang sesuai dengan sebuah key, dan pakai satu handler dengan key hasil perhitungan: setForm({ ...form, [e.target.name]: e.target.value }).

Kenapa textarea di React memakai value, bukan children?

Di HTML, teks textarea berada di antara tag-nya, tetapi di React kamu mengirimnya sebagai value (atau defaultValue), sama seperti input. Dengan begitu, setiap field teks di form React bekerja dengan cara yang sama.

Apa itu form action di React 19?

Di React 19, kamu bisa mengirim fungsi ke <form action={fn}>. React mencegah halaman dimuat ulang, memanggil fungsi itu dengan FormData milik form, dan mengatur ulang field yang tidak terkontrol setelah selesai. useActionState menambahkan flag pending dan hasil di atasnya.

Ilustrasi bahasa pemrograman di Coddy

Belajar coding dengan Coddy

Mulai