Home >Web Front-end >JS Tutorial >Forms with React Hook Form Zod

Forms with React Hook Form Zod

Patricia Arquette
Patricia ArquetteOriginal
2024-11-09 11:19:02885browse

Introduction

When I started programming, I needed to write a lot of code in pure JavaScript to collect data from a form. Since then, web development has evolved so much that today we have libraries that abstract much of this work, making it easier to manage form data.

In this article, I will show you how to use React Hook Form to work with form data and zod to validate this data in an efficient and organized way.

I'm in a hurry, give me the complete code

It's in your hand:

import { Label } from '@/components/ui/label';
import { Input } from '@/components/ui/input';
import { Button } from '@/components/ui/button';
import { Gamepad, Gamepad2 } from 'lucide-react';
import { useForm } from 'react-hook-form';
import { z } from 'zod';
import { zodResolver } from '@hookform/resolvers/zod';
import { toast, Toaster } from 'sonner';

const signUpForm = z
  .object({
    name: z
      .string()
      .min(2, { message: 'Nome deve ter ao menos 2 caracteres' })
      .max(50, { message: 'Nome deve ter no máximo 50 caracteres' }),
    email: z.string().email().max(100, { message: 'E-mail deve ter no máximo 100 caracteres' }),
    password: z.string().max(100, { message: 'Senha deve ter no máximo 100 caracteres' }),
    confirm: z.string(),
  })
  .refine((data) => data.password === data.confirm, {
    message: 'Senhas não conferem!',
    path: ['confirm'],
  });

type SignUpForm = z.infer<typeof signUpForm>;

export function App() {
  const {
    handleSubmit,
    register,
    reset,
    formState: { isSubmitting, errors },
  } = useForm<SignUpForm>({
    resolver: zodResolver(signUpForm),
  });

  async function handleSignup(data: SignUpForm) {
    console.log(data);
    await new Promise((resolve) => {
      setTimeout(resolve, 2000);
    });
    reset();
    toast.success('Conta criada com sucesso!');
  }

  return (
    <>
      <Toaster richColors />
      <div className="min-h-screen lg:grid lg:grid-cols-2 antialiased gap-8">
        <div className="hidden lg:flex h-full justify-center border-r border-foreground/5 bg-foreground text-muted-foreground items-center gap-3 text-lg">
          <Gamepad2 />
          <span className="font-semibold">gamers.shop</span>
        </div>
        <div className="flex flex-col items-center justify-center gap-6 min-h-screen">
          <div className="px-10 w-96 h-full flex flex-col justify-center items-center lg:w-[500px]">
            <h1 className="flex items-center gap-2 mb-4 text-2xl font-semibold tracking-tight">
              <Gamepad />
              Crie sua conta
              <Gamepad />
            </h1>
            <form onSubmit={handleSubmit(handleSignup)} className="space-y-4 w-full ">
              <div className="space-y-2">
                <Label htmlFor="name">Nome</Label>
                <Input>



<h2>
  
  
  Tutorial
</h2>

<h3>
  
  
  Estruturando o Formulário
</h3>

<p>Primeiro, criei um formulário com quatro campos: nome, e-mail, senha e confirmação de senha. Para facilitar o desenvolvimento da interface, utilizei shadcn, tailwind e lucide-react. O uso de classes CSS pode parecer um pouco detalhado, mas elas ajudam a manter um design consistente.<br>
</p>

<pre class="brush:php;toolbar:false"><form className="space-y-4 w-full ">
  <div className="space-y-2">
    <Label htmlFor="name">Nome</Label>
    <Input>



<p>Criei 4 campos nesse form: nome, e-mail, password e confirm. Preciso validá-los de alguma forma. Como esse exemplo server para explicar o uso de zod, evitei utilizar as propriedades nativas do HTML (required, maxlength etc).</p>

<h3>
  
  
  Validação de Dados com Zod
</h3>

<p>Para garantir que os dados inseridos nos campos estão corretos, criei um schema de validação com o zod. O schema define as restrições para cada campo e personaliza as mensagens de erro:<br>
</p>

<pre class="brush:php;toolbar:false">import { z } from 'zod';

const signUpFormSchema = z
  .object({
    name: z
      .string()
      .min(2, { message: 'Nome deve ter ao menos 2 caracteres' })
      .max(50, { message: 'Nome deve ter no máximo 50 caracteres' }),
    email: z.string().email().max(100, { message: 'E-mail deve ter no máximo 100 caracteres' }),
    password: z.string().max(100, { message: 'Senha deve ter no máximo 100 caracteres' }),
    confirm: z.string(),
  })
  .refine((data) => data.password === data.confirm, {
    message: 'Senhas não conferem!',
    path: ['confirm'],
  });

This schema defines the types and validations required for each field. The .refine() method was used to ensure that the passwords entered in the "password" and "confirm" fields are the same.

.refine((data) => data.password === data.confirm, {
  message: 'Senhas não conferem!',
  path: ['confirm'],
});

Integration with React Hook Form and Zod Resolver

React Hook Form is a form library that improves performance by reducing unnecessary re-renders and simplifying data manipulation. I used useForm() to configure the form, passing the validation schema through zodResolver:

import { zodResolver } from '@hookform/resolvers/zod';
import { useForm } from 'react-hook-form';

type SignUpForm = z.infer<typeof signUpFormSchema>;

const {
    handleSubmit,
    register,
    reset,
    formState: { isSubmitting, errors },
  } = useForm<SignUpForm>({
    resolver: zodResolver(signUpFormSchema),
  });

The functions and variables I used from useForm() are:

  • handleSubmit: handles form submission.
  • register: binds form fields to React Hook Form data management.
  • reset: resets the form.
  • isSubmitting: indicates whether the form is being submitted.
  • errors: stores validation errors for each field. ### Form Submission Function To simulate form submission, I created the handleSignup function, which adds a waiting time to view the isSubmitting status and displays a success message with the toast:
async function handleSignup(data: SignUpForm) {
  console.log(data);
  await new Promise((resolve) => {
    setTimeout(resolve, 2000);
  });
  reset();
  toast.success('Conta criada com sucesso!');
}

Then I added the function to the form:

<form onSubmit={handleSubmit(handleSignup)} className="space-y-4 w-full">

And finally, I used register to name which field belongs to which property, and showed the errors (if they exist):

<div className="space-y-2">
  <Label htmlFor="name">Name</Label>
  <input>



<p>The result looked like this:</p>

<p><img src="https://img.php.cn/upload/article/000/000/000/173112234459208.jpg" alt="Formulários com React Hook Form   Zod"></p>

<h2>
  
  
  Final Considerations
</h2>

<p>In this text, I showed a simple way to integrate React Hook Form and zod to validate uncontrolled forms. The library also works with controlled components, so consult the documentation to explore more options.</p>


          

            
        

The above is the detailed content of Forms with React Hook Form Zod. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn