Form di React — React

Form daftar akun, form login, form pencarian, form checkout — tiap aplikasi web pasti punya form. Cara React handle form unik: bukan baca nilai input dari DOM (

Form daftar akun, form login, form pencarian, form checkout — tiap aplikasi web pasti punya form. Cara React handle form unik: bukan baca nilai input dari DOM (kayak vanilla), tapi simpan nilai input di React state. Setiap keystroke → update state → React re-render dengan nilai baru. Pattern ini namanya controlled component — React jadi "sumber kebenaran tunggal", DOM cuma reflect state.

🤔 Kenapa rumit dibanding vanilla? Vanilla HTML form: ketik di input, browser handle storage internal, baca pakai input.value saat submit. React controlled: tiap ketik trigger event → setState → re-render. Kelihatan ribet, tapi reward-nya GEDE: validasi real-time gampang, format on-the-fly (uppercase, currency formatting), conditional disable, undo/redo — semuanya gratis karena state sentralisasi.

function LoginForm() {
  const [email, setEmail] = useState("")

  return (
    <input
      value={email}                              // state → DOM
      onChange={(e) => setEmail(e.target.value)}  // DOM → state
    />
  )
}

Loop dua arah: state → input value (display) + input change → state (capture). Itu yang bikin "controlled".

Controlled vs Uncontrolled

Controlled Uncontrolled
Nilai = React state Nilai = DOM langsung
value={state} + onChange defaultValue (optional)
Validasi real-time gampang Akses pakai useRef
Re-render tiap keystroke Gak re-render saat ketik
Default modern React Hanya untuk kasus khusus

Form Submission

function App() {
  const [name, setName] = useState("")

  const handleSubmit = (e) => {
    e.preventDefault()  // WAJIB — cegah reload halaman
    console.log("Submitted:", name)
    // Kirim ke API: fetch("/api/users", { method: "POST", ... })
  }

  return (
    <form onSubmit={handleSubmit}>
      <input value={name} onChange={(e) => setName(e.target.value)} />
      <button type="submit">Kirim</button>
    </form>
  )
}

Multiple Inputs — Object State

function RegisterForm() {
  const [form, setForm] = useState({
    name: "", email: "", password: "",
  })

  const handleChange = (e) => {
    const { name, value } = e.target
    setForm(prev => ({ ...prev, [name]: value }))  // dynamic key
  }

  return (
    <form>
      <input name="name" value={form.name} onChange={handleChange} />
      <input name="email" value={form.email} onChange={handleChange} />
      <input name="password" type="password" value={form.password} onChange={handleChange} />
    </form>
  )
}

Pattern ini ngirit code — satu handler buat banyak field via name attribute.

🎭 Analogi sehari-hari

Controlled form itu kayak buku tulis di kelas. Tiap kamu nulis huruf di buku, guru langsung nyatat ulang di papan tulis (state). Pas guru hapus papan, buku kamu juga otomatis ke-update — papan tulis jadi sumber kebenaran. Vanilla form lebih kayak buku tulis pribadi: kamu nulis sendiri, guru cuma ngecek pas ulangan (saat submit). Cara React ribet di awal — tiap keystroke ada interaksi — tapi pas mau validasi real-time ("password kurang 8 karakter") atau format on-the-fly ("auto-uppercase"), kekuatan pattern ini langsung kelihatan.

⚠️ Jebakan yang sering ditemui

🎯 State form — pilih bentuk apa?

  • 1-2 field → useState terpisah (useState("") per field)
  • 3-5 field related → useState object ({ name, email, ... }) + spread updater
  • Form kompleks (10+ field, validasi rumit, multi-step) → library: React Hook Form atau Formik (jangan bikin sendiri)
  • Form yang gak butuh re-render saat ketik (search box dengan debounce) → uncontrolled + useRef
  • Form fields dinamis (tambah/hapus field array) → useFieldArray dari React Hook Form

Aturan praktis: useState manual buat form sederhana. React Hook Form pas form mulai gemuk (validasi + nested + dynamic).

TL;DR: Controlled form = nilai input simpan di React state. value={state} + onChange={e => setState(e.target.value)}. WAJIB e.preventDefault() di submit (cegah reload). Multi-field? Pakai object state + spread updater dengan dynamic key [e.target.name]. Number input → e.target.value selalu string (convert manual). Checkbox pakai checked bukan value. Form kompleks → React Hook Form.

Yang akan kamu pelajari