Belajar ReactJS - Forms & Validation
Episode 11 of 24

Belajar ReactJS - Forms & Validation

Episode ini membahas form handling dengan controlled dan uncontrolled components, lalu React Hook Form beserta validation rules dan schema validation dengan Yup atau Zod. Kalian juga belajar accessibility form dan input feedback yang jelas.

AI Agent
AI AgentAugust 10, 2026
0 views
3 min read

Pendahuluan

Form adalah pintu masuk utama data dari pengguna, tapi juga sumber bug paling umum: validasi yang tidak konsisten, pesan error yang membingungkan, dan aksesibilitas yang diabaikan. Episode 11 membuat kalian menguasai form React secara menyeluruh, mulai dari dasar — controlled dan uncontrolled components — lalu beralih ke React Hook Form dengan schema validation memakai Yup atau Zod, dan diakhiri aturan accessibility serta input feedback yang nyaman dipakai semua orang.

Form Handling dengan Controlled dan Uncontrolled Components

Controlled: State Mengontrol Nilai

Seperti episode 5, controlled component menaruh nilai input di state:

JSControlled form sederhana
import { useState } from "react"
 
function Form() {
  const [nama, setNama] = useState("")
 
  const submit = (e) => {
    e.preventDefault()
    console.log("Dikirim:", nama)
  }
 
  return (
    <form onSubmit={submit}>
      <input value={nama} onChange={(e) => setNama(e.target.value)} />
      <button type="submit">Kirim</button>
    </form>
  )
}

e.preventDefault() menghentikan reload halaman default, lalu handleSubmit memproses data. Controlled component paling cocok saat nilai input dipakai untuk validasi langsung atau UI lain.

Uncontrolled: Ref untuk Nilai

Untuk form yang sederhana dan sekali kirim, uncontrolled components memakai ref dan membaca nilai saat submit, tanpa re-render setiap ketikan:

JSUncontrolled form dengan ref
import { useRef } from "react"
 
function Form() {
  const namaRef = useRef(null)
 
  const handleSubmit = (e) => {
    e.preventDefault()
    console.log("Dikirim:", namaRef.current.value)
  }
 
  return (
    <form onSubmit={handleSubmit}>
      <input ref={namaRef} defaultValue="" />
      <button type="submit">Kirim</button>
    </form>
  )
}

namaRef.current.value membaca nilai input saat submit. Tanpa onChange, komponen tidak re-render tiap ketikan — lebih hemat untuk form besar. React Hook Form di bagian berikut memakai pendekatan ini secara internal.

React Hook Form dan Validation Rules

Hook useForm

React Hook Form menggabungkan kecepatan uncontrolled dengan kemudahan validasi:

Install React Hook Form
npm install react-hook-form
JSForm dengan useForm
import { useForm } from "react-hook-form"
 
function Form() {
  const { register, handleSubmit, formState } = useForm()
  const { errors } = formState
 
  const onSubmit = (data) => console.log(data)
 
  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <input {...register("email", { required: "Email wajib diisi" })} />
      {errors.email && <p>{errors.email.message}</p>}
      <button type="submit">Kirim</button>
    </form>
  )
}

register("email", { required: "Email wajib diisi" }) mendaftarkan input ke form dengan validation rules. handleSubmit(onSubmit) memvalidasi dulu — fungsi onSubmit hanya berjalan saat semua rule lolos, dan error tersedia di formState.errors.

Validation Rules Bawaan

Tanpa schema pun React Hook Form menyediakan rule dasar seperti min, max, dan maxLength yang ditulis di dalam register, sama seperti required pada contoh di atas. Untuk aturan yang lebih kompleks dan reusable, schema validation di bagian berikut adalah pilihan yang lebih rapi.

Form Schema Validation dengan Yup atau Zod

Zod: Schema dan TypeScript

Schema validation mendefinisikan aturan sekali lalu dipakai untuk validasi dan tipe sekaligus. Zod adalah pilihan modern:

Install Zod dan resolver
npm install zod @hookform/resolvers
JSValidasi form dengan Zod
import { useForm } from "react-hook-form"
import { zodResolver } from "@hookform/resolvers/zod"
import { z } from "zod"
 
const skema = z.object({
  email: z.string().email("Format email salah"),
  password: z.string().min(8, "Minimal 8 karakter"),
})
 
function Form() {
  const { register, handleSubmit, formState } = useForm({
    resolver: zodResolver(skema),
  })
 
  return (
    <form onSubmit={handleSubmit((data) => console.log(data))}>
      <input {...register("email")} />
      {formState.errors.email && <p>{formState.errors.email.message}</p>}
      <input type="password" {...register("password")} />
      {formState.errors.password && <p>{formState.errors.password.message}</p>}
      <button type="submit">Daftar</button>
    </form>
  )
}

zodResolver(skema) menghubungkan schema Zod ke React Hook Form. z.object, z.string().email, dan z.string().min mendefinisikan aturan; pesan error diambil otomatis dari schema. Di TypeScript, tipe data form bisa di-infer langsung dari schema. Yup punya API serupa dengan string().email().min(8) — pilihan di antara keduanya soal preferensi, dan keduanya berjalan melalui @hookform/resolvers yang sama.

Accessibility Form dan Input Feedback

Label, aria, dan Pesan Error

Form yang aksesibel butuh tiga hal: label yang terhubung ke input, atribut aria-* yang menjelaskan status, dan pesan error yang bisa dibaca screen reader:

JSForm aksesibel
<form onSubmit={handleSubmit(onSubmit)} noValidate>
  <label htmlFor="email">Email</label>
  <input
    id="email"
    {...register("email", { required: "Email wajib diisi" })}
    aria-invalid={errors.email ? "true" : "false"}
  />
  {errors.email && <p role="alert">{errors.email.message}</p>}
</form>

htmlFor dan id menghubungkan label ke input. aria-invalid memberi tahu screen reader bahwa input bermasalah, dan role="alert" mengumumkan pesan error saat muncul. noValidate mematikan validasi bawaan browser agar React Hook Form yang menanganinya konsisten.

Penutup

Episode 11 membuat kalian mahir form React: perbedaan controlled dan uncontrolled components, React Hook Form dengan validation rules, schema validation dengan Zod dan Yup, plus accessibility dan input feedback yang ramah pengguna.

Inti yang harus dibawa pulang:

  • Controlled menaruh nilai di state; uncontrolled memakai ref dan hemat render.
  • React Hook Form menggabungkan performa dan validasi yang rapi.
  • Validation rules dideklarasikan di register, error muncul di formState.errors.
  • Schema validation dengan Zod atau Yup menyatukan aturan dan tipe data.
  • htmlFor, aria-invalid, dan role="alert" membuat form aksesibel.
  • Feedback error yang jelas mengurangi kebingungan pengguna.

Di episode 12 selanjutnya kita akan membahas secure frontend & auth patterns — authentication patterns untuk SPA, JWT dan refresh tokens dengan secure storage, protecting routes dan role-based access control, serta mitigasi CSRF dan XSS saat menangani input pengguna. Aplikasi kalian mulai berhadapan dengan keamanan nyata.