🔧 AI Nachrichten Major AI platforms go down in unprecedented simultaneous outage(03.09.2026 um 17:34 Uhr)
🔧 AI Nachrichten ChatGPT, Claude, and Grok Down? Users Report Widespread Outages(03.09.2026 um 19:14 Uhr)
🔧 AI Nachrichten OpenAI Launches GPT-6 Astra, Says We May Have Entered the AGI Era(03.09.2026 um 22:08 Uhr)
🔧 AI Nachrichten Claude Comes to CarPlay as Fifth Major AI Chatbot App(05.09.2026 um 05:31 Uhr)
🔧 AI Nachrichten OpenAI’s GPT-6 Astra Is AGI, Says NVIDIA CEO Jensen Huang(07.09.2026 um 06:31 Uhr)
🔧 AI Nachrichten Blame AI companies for Mac mini and Mac Studio shortage(31.08.2026 um 10:32 Uhr)
🔧 AI Nachrichten Major AI platforms go down in unprecedented simultaneous outage(03.09.2026 um 17:34 Uhr)
🔧 AI Nachrichten ChatGPT, Claude, and Grok Down? Users Report Widespread Outages(03.09.2026 um 19:14 Uhr)
🔧 AI Nachrichten OpenAI Launches GPT-6 Astra, Says We May Have Entered the AGI Era(03.09.2026 um 22:08 Uhr)
🔧 AI Nachrichten Claude Comes to CarPlay as Fifth Major AI Chatbot App(05.09.2026 um 05:31 Uhr)
🔧 AI Nachrichten OpenAI’s GPT-6 Astra Is AGI, Says NVIDIA CEO Jensen Huang(07.09.2026 um 06:31 Uhr)
🔧 AI Nachrichten Blame AI companies for Mac mini and Mac Studio shortage(31.08.2026 um 10:32 Uhr)

🔧 Programmierung 🕛 kürzlich 7 Min Lesezeit
0

Formulários com React Hook Form + Zod

↗ Quelle (dev.to)
🗣️ Stimme:
📑 Inhaltsübersicht




Introdução



Quando comecei a programar, precisava escrever bastante código em JavaScript puro para coletar dados de um formulário. De lá para cá, o desenvolvimento web evoluiu tanto que hoje temos bibliotecas que abstraem grande parte desse trabalho, facilitando a gestão dos dados dos formulários.



Neste artigo, vou mostrar como utilizar o para validar esses dados de forma eficiente e organizada.






Tô com pressa, me dê o código completo



Tá na mão:




CODE
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 id="name" type="text" {...register('name')} />
{errors.name && <span className="text-sm text-red-500">{errors.name.message}</span>}
{}
</div>
<div className="space-y-2">
<Label htmlFor="email">Email</Label>
<Input id="email" type="email" {...register('email')} />
{errors.email && <span className="text-sm text-red-500">{errors.email.message}</span>}
</div>
<div className="space-y-2">
<Label htmlFor="password">Senha</Label>
<Input id="password" type="password" {...register('password')} />
{errors.password && <span className="text-sm text-red-500">{errors.password.message}</span>}
</div>
<div className="space-y-2">
<Label htmlFor="confirm">Confirme a senha</Label>
<Input id="confirm" type="password" {...register('confirm')} />
{errors.confirm && <span className="text-sm text-red-500">{errors.confirm.message}</span>}
</div>

<Button className="w-full" type="submit" disabled={isSubmitting}>
Criar conta
</Button>
</form>
</div>
</div>
</div>
</>
);
}










Tutorial






Estruturando o Formulário



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.




CODE
<form className="space-y-4 w-full ">
<div className="space-y-2">
<Label htmlFor="name">Nome</Label>
<Input id="name" type="text" placeholder="Digite o seu nome"/>
</div>
<div className="space-y-2">
<Label htmlFor="email">Email</Label>
<Input id="email" type="email" placeholder="Digite o seu e-mail"/>
</div>
<div className="space-y-2">
<Label htmlFor="password">Senha</Label>
<Input id="password" type="password" placeholder="Digite uma senha"/>
</div>
<div className="space-y-2">
<Label htmlFor="confirm">Confirme a senha</Label>
<Input id="confirm" type="password" placeholder="Digite a senha novamente"/>
</div>

<Button className="w-full" type="submit">
Criar conta
</Button>
</form>






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).






Validação de Dados com Zod



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:




CODE
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'],
});







Esse schema define os tipos e as validações necessárias para cada campo. O método .refine() foi utilizado para garantir que as senhas digitadas nos campos "password" e "confirm" são iguais.




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









Integração com React Hook Form e Zod Resolver



O React Hook Form é uma biblioteca de formulários que melhora o desempenho ao reduzir re-renderizações desnecessárias e simplificar a manipulação de dados. Usei o useForm() para configurar o formulário, passando o schema de validação por meio do zodResolver:




CODE
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),
});






As funções e variáveis que utilizei de useForm() são:





  • handleSubmit: lida com o envio do formulário.


  • register: vincula campos do formulário ao gerenciamento de dados do React Hook Form.


  • reset: redefine o formulário.


  • isSubmitting: indica se o formulário está sendo enviado.


  • errors: armazena erros de validação de cada campo.
    ### Função de Envio do Formulário
    Para simular o envio do formulário, criei a função handleSignup, que adiciona um tempo de espera para visualizar o estado isSubmitting e exibe uma mensagem de sucesso com o toast:




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






Depois adicionei a função ao form:




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






E por fim, utilizei o register para denominar qual campo pertence a qual propriedade, e mostrei os erros (caso eles existam):




CODE
<div className="space-y-2">
<Label htmlFor="name">Nome</Label>
<Input id="name" type="text" {...register('name')} placeholder="Digite o seu nome" />
{errors.name && <span className="text-sm text-red-500">{errors.name.message}</span>}
</div>






O resultado ficou assim:



para explorar mais opções.

Vollständiger Original-Bericht
Ausführliche Details, Code-Beispiele & Hersteller-Stellungnahme auf dev.to.
↗ Original-Artikel auf dev.to lesen
Wie bewertest du diesen Beitrag?
1 Klick Feedback
Teilen mit Netzwerk & Team:

Community-Analysen & Experten-Meinungen 0

Verfasse deine eigene Analyse, teile Workarounds oder diskutiere diesen Vorfall im Blog.
Noch keine Community-Analyse verfasst. Markiere einen Textabschnitt oder klicke oben auf Eigene Analyse verfassen“!
Community Pulse: Relevanz-Einschätzung
1 Klick Experten-Votum
🔴 Akute Relevanz 0%
🟡 In Evaluierung 0%
🟢 Keine Auswirkung 0%
Spannende Innovation 0%
Verwandte Story-Cluster & Quellen (Vektor-KI)
Port 8095 Engine
3 Quellen
GPT-6 Astra Release Today? OpenAI’s Next Major AI Model Is Almost Here
1 Quelle
Apple accuses OpenAI of destroying evidence as trade-secrets fight intensifies
1 Quelle
Major AI platforms go down in unprecedented simultaneous outage
Ähnliche Beiträge
🔍 Verwandte News

Auch interessante Nachrichten Formulários com React Hook Form + Zod

Thematisch verwandte Begriffe: Formulários, React, Hook, Form · 6 Treffer

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...