Validasi Form Type-Safe Menggunakan Zod dan React Hook Form

Validasi Form Type-Safe Menggunakan Zod dan React Hook Form

Tantangan Penanganan Form pada React

Mengelola input pengguna di React sering kali membutuhkan banyak boilerplate state (useState untuk setiap field), pesan error manual, dan risiko tipe data yang tidak sinkron antara validasi frontend dan API backend.


Solusi: Combination Zod & React Hook Form

  • Zod: Pustaka deklarasi skema tipe-safe TypeScript first.
  • React Hook Form: Pustaka pengelola state formulir yang sangat hemat re-render.

1. Mendefinisikan Skema Zod

import { z } from 'zod';

export const contactFormSchema = z.object({
  name: z.string().min(2, "Nama minimal 2 karakter"),
  email: z.string().email("Format email tidak valid"),
  message: z.string().min(10, "Pesan minimal 10 karakter"),
});

// Inferensi Tipe TypeScript Otomatis!
export type ContactFormValues = z.infer<typeof contactFormSchema>;

2. Mengintegrasikan dengan React Hook Form

Gunakan @hookform/resolvers/zod untuk menyambungkan skema ke komponen formulir:

import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { contactFormSchema, type ContactFormValues } from './schema';

export function ContactForm() {
  const {
    register,
    handleSubmit,
    formState: { errors, isSubmitting },
  } = useForm<ContactFormValues>({
    resolver: zodResolver(contactFormSchema),
  });

  const onSubmit = async (data: ContactFormValues) => {
    await fetch('/api/contact', {
      method: 'POST',
      body: JSON.stringify(data),
    });
  };

  return (
    <form onSubmit={handleSubmit(onSubmit)} className="space-y-4">
      <div>
        <input {...register('name')} placeholder="Nama Lengkap" className="input" />
        {errors.name && <p className="text-red-500 text-xs mt-1">{errors.name.message}</p>}
      </div>

      <div>
        <input {...register('email')} type="email" placeholder="Email" className="input" />
        {errors.email && <p className="text-red-500 text-xs mt-1">{errors.email.message}</p>}
      </div>

      <button type="submit" disabled={isSubmitting} className="btn">
        {isSubmitting ? 'Mengirim...' : 'Kirim Pesan'}
      </button>
    </form>
  );
}

Kesimpulan

Kombinasi Zod dan React Hook Form menghapus re-render yang tidak perlu, menjamin validasi skema yang konsisten, dan memfasilitasi inferred types secara instan dari skema ke handler API!

Command Palette

Search for a command to run...