Formulários com React Hook Form e Zod
Primeiro, precisamos instalar as dependências necessárias:
yarn add react-hook-form @hookform/resolvers zod
yarn add react-hook-form @hookform/resolvers zod
Agora, fazemos a importação delas:
import { zodResolver } from '@hookform/resolvers/zod'
import { SubmitHandler, useForm } from 'react-hook-form'
import { z } from 'zod'
import { zodResolver } from '@hookform/resolvers/zod'
import { SubmitHandler, useForm } from 'react-hook-form'
import { z } from 'zod'
Usamos o z.object()
z.object()
para criar um novo schema. O schema contém os campos que compõem o nosso formulário.
const formSchema = z
.object({
name: z.string().min(1, 'O campo Nome é obrigatório').max(100),
email: z.string().min(1, 'O campo E-mail é obrigatório').email('O e-mail é inválido'),
password: z
.string()
.min(1, 'O campo Senha é obrigatório')
.min(8, 'A senha deve ter no mínimo 8 caracteres'),
confirmPassword: z.string().min(1, 'O campo Confirmar Senha é obrigatório'),
terms: z.literal(true, {
errorMap: () => ({ message: 'Você deve aceitar os termos e condições' }),
}),
})
const formSchema = z
.object({
name: z.string().min(1, 'O campo Nome é obrigatório').max(100),
email: z.string().min(1, 'O campo E-mail é obrigatório').email('O e-mail é inválido'),
password: z
.string()
.min(1, 'O campo Senha é obrigatório')
.min(8, 'A senha deve ter no mínimo 8 caracteres'),
confirmPassword: z.string().min(1, 'O campo Confirmar Senha é obrigatório'),
terms: z.literal(true, {
errorMap: () => ({ message: 'Você deve aceitar os termos e condições' }),
}),
})
Para validar a confirmação de senha, usamos o método refine()
refine()
, que aceita dois parâmetros: um callback e um objeto.
const formSchema = z
.object({
// Resto do código
...
}).refine((data) => data.password === data.confirmPassword, {
path: ['confirmPassword'],
message: 'Senhas não são iguais',
})
const formSchema = z
.object({
// Resto do código
...
}).refine((data) => data.password === data.confirmPassword, {
path: ['confirmPassword'],
message: 'Senhas não são iguais',
})
Usamos o z.infer
z.infer
para extrair a tipagem do formulário:
type FormSchemaType = z.infer<typeof formSchema>
type FormSchemaType = z.infer<typeof formSchema>
Por último, dentro do componente de formulário, implementamos o React Hook Form passando como resolver
resolver
o zodResolver()
zodResolver()
. O zodResolver()
zodResolver()
recebe como parâmetro o schema criado anteriormente.
export const Form = () => {
const {
register,
handleSubmit,
reset,
formState: { errors, isSubmitting },
} = useForm<FormSchemaType>({
// Fazendo o uso do zodResolver
resolver: zodResolver(formSchema),
})
const onSubmit: SubmitHandler<FormSchemaType> = async (data) => {
console.log(data)
}
// Formulário com React Hook Form
return (
<form onSubmit={handleSubmit(onSubmit)}>
...
</form>
)
}
export const Form = () => {
const {
register,
handleSubmit,
reset,
formState: { errors, isSubmitting },
} = useForm<FormSchemaType>({
// Fazendo o uso do zodResolver
resolver: zodResolver(formSchema),
})
const onSubmit: SubmitHandler<FormSchemaType> = async (data) => {
console.log(data)
}
// Formulário com React Hook Form
return (
<form onSubmit={handleSubmit(onSubmit)}>
...
</form>
)
}