讲师中心 微信公众号
AI工具推荐 视频效率加速

使用 React Hook Form + Zod 构建表单

秋丽君_8552

秋丽君_8552

发布时间:2024-11-08 13:04:00

|

1114人浏览过

|

来源于dev.to

转载

介绍

当我开始编程时,我需要用纯 javascript 编写大量代码来从表单收集数据。从那时起,web 开发已经发展得如此之快,以至于今天我们有了抽象了大部分工作的库,从而促进了表单数据的管理。

在本文中,我将向您展示如何使用 react hook form 来处理表单数据,并使用 zod 以高效且有组织的方式验证这些数据。

我很着急,请给我完整的代码

它在你手里:

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>
    </>
  );
}

教程

构建表格

首先,我创建了一个包含四个字段的表单:姓名、电子邮件、密码和密码确认。为了方便接口的开发,我使用了shadcn、tailwind和lucide-react。使用 css 类可能看起来有点冗长,但它们有助于保持一致的设计。

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

我在此表单中创建了 4 个字段:姓名、电子邮件、密码和确认。我需要以某种方式验证它们。由于此示例用于解释 zod 的使用,因此我避免使用本机 html 属性(必需、最大长度等)。

使用 zod 进行数据验证

为了确保在字段中输入的数据正确,我使用 zod 创建了一个验证模式。该架构定义了每个字段的限制并自定义错误消息:

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

此架构定义了每个字段所需的类型和验证。使用 .refine() 方法来确保“密码”和“确认”字段中输入的密码相同。

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

与 react hook form 和 zod resolver 集成

react hook form 是一个表单库,它通过减少不必要的重新渲染和简化数据操作来提高性能。我使用 useform() 来配置表单,通过 zodresolver 传递验证架构:

Digital Twin Discharge Drafter
Digital Twin Discharge Drafter

用于撰写患者出院小结、制定个性化出院指导、模拟出院后结局、降低再入院率

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

我在 useform() 中使用的函数和变量是:

  • handlesubmit:处理表单提交。
  • register:将表单字段绑定到react hook form数据管理。
  • 重置:重置表单。
  • issubmitting:表示表单是否正在提交。
  • 错误:存储每个字段的验证错误。 ### 表单提交功能 为了模拟表单提交,我创建了handlesignup函数,它添加了一个等待时间来查看issubmitting状态并用toast显示成功消息:
async function handlesignup(data: signupform) {
  console.log(data);
  await new promise((resolve) => {
    settimeout(resolve, 2000);
  });
  reset();
  toast.success('conta criada com sucesso!');
}

然后我将函数添加到表单中:

<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')} placeholder="Digite o seu nome" />
  {errors.name && <span className="text-sm text-red-500">{errors.name.message}</span>}
</div>

结果如下所示:

使用 React Hook Form + Zod 构建表单

最后的考虑因素

在本文中,我展示了一种集成 react hook form 和 zod 来验证不受控制的表单的简单方法。该库还可以使用受控组件,因此请查阅文档以探索更多选项。

热门AI工具

更多
WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

讯飞绘文

讯飞绘文是一款由科大讯飞推出的一站式 AIGC 内容运营平台。

立刻MV
立刻MV Hot

立刻MV是一款AI文本写作工具,AI 音乐视频(MV)创作工具。

Laper
Laper Hot

Laper是专为编剧、导演和制片人推出的 AI 原生剧本创作工具。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

UpDream
UpDream Hot

一款AI视频创作工具,主要用于哔哩哔哩推出的自研AI视频创作工具,适合需要提升相关任务效率的用户。

LibLibAI
LibLibAI Hot

一款AI视频创作工具,主要用于国内领先的AI创意平台,以海量模型、低门槛操作与“创作-分享-商业化”生态,让小白与专业创作者都能高效实现图文乃至视频创意表达,适合需要提升相关任务效率的用户。

切问学术

切问学术是一款AI论文写作工具,复旦大学NLP团队推出的AI学术智能体。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

相关专题

更多
硬盘接口类型介绍
硬盘接口类型介绍

硬盘接口类型有IDE、SATA、SCSI、Fibre Channel、USB、eSATA、mSATA、PCIe等等。详细介绍:1、IDE接口是一种并行接口,主要用于连接硬盘和光驱等设备,它主要有两种类型:ATA和ATAPI,IDE接口已经逐渐被SATA接口;2、SATA接口是一种串行接口,相较于IDE接口,它具有更高的传输速度、更低的功耗和更小的体积;3、SCSI接口等等。

3008

2023.10.19

PHP接口编写教程
PHP接口编写教程

本专题整合了PHP接口编写教程,阅读专题下面的文章了解更多详细内容。

4129

2025.10.17

php8.4实现接口限流的教程
php8.4实现接口限流的教程

PHP8.4本身不内置限流功能,需借助Redis(令牌桶)或Swoole(漏桶)实现;文件锁因I/O瓶颈、无跨机共享、秒级精度等缺陷不适用高并发场景。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

3649

2025.12.29

java接口相关教程
java接口相关教程

本专题整合了java接口相关内容,阅读专题下面的文章了解更多详细内容。

346

2026.01.19

AI视频生成软件推荐
AI视频生成软件推荐

本专题汇总了当前主流的AI视频生成软件推荐与排行榜单,涵盖seko、AniShort、剧云、Lovart、LiblibAI及立刻mv等热门工具。同时整理了各软件在文生视频、图生视频、时长限制、画质表现及免费额度等方面的差异对比,助您快速选对适合创作需求的AI视频生成工具。

100

2026.09.16

ai生成视频的工具免费版合集
ai生成视频的工具免费版合集

本专题汇总了当前免费AI生成视频工具的排行榜与推荐清单,涵盖seko、讯飞智作、AniShort及剧云、Lovart等多模型集成平台。同时整理了各工具的免费额度、输出时长、水印政策及适用场景差异,助您快速选择合适工具开启AI视频创作。

20

2026.09.16

Pandas时间序列分析与可视化报表
Pandas时间序列分析与可视化报表

本专题整理Pandas日期转换、时间索引、重采样、滚动窗口、时区处理、plot绘图、Styler表格样式和报表输出方法。

40

2026.09.16

Pandas数据筛选索引与清洗处理
Pandas数据筛选索引与清洗处理

本专题整理Pandas中的loc、iloc、条件筛选、query查询、缺失值处理、重复值删除、类型转换和字符串列清洗方法。

40

2026.09.16

Pandas数据读取导入与文件导出处理
Pandas数据读取导入与文件导出处理

本专题整理Pandas读取CSV、Excel、JSON、SQL、Parquet等文件的方法,以及to_csv、to_excel、to_sql和to_parquet等常用数据导出流程。

20

2026.09.16

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Sass 教程
Sass 教程

共14课时 | 1.4万人学习

Bootstrap 5教程
Bootstrap 5教程

共46课时 | 5.5万人学习

CSS教程
CSS教程

共754课时 | 92.9万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn