为了账号安全,请及时绑定邮箱和手机立即绑定

使用React Hook Form、Zod和Shadcn轻松构建React表单

每个开发者都会遇到表单,无论是作为用户还是开发者。表单在大多数网站上都很重要,但它们的复杂度差异很大——从简单的三字段联系表单到复杂的多页表单,包含150个字段、动态验证和异步检查。

在这篇帖子中,我们将探讨如何使用 React Hook Form、Zod 和 Shadcn UI 来创建一个灵活且对开发者友好的解决方案,轻松应对各种表单需求情况。

大卫·贝克汉姆和维多利亚的表情包

我们将要创建的表单

这里是我们在这篇文章中要开发的表单。我打算再写一篇关于表单高级用法的文章,那篇文章会更复杂,更有趣。请继续关注,😃

如图所示,这个表单示例

认识一下这些工具:

我们来看看我们将用来构建和管理表单的那些栈。

React 与 Wasp

  • 框架:一个Wasp,一个适用于 React、Node.js 和 Prisma 的全栈框架。
  • 使用 React 实现快速高效的全栈 Web 开发和部署。

React 钩子表单组件

  • 一个轻量级的 React 表单库,主要通过其 useForm 钩子来创建表单。
  • 处理表单验证和错误管理,提供灵活的验证方式,并与各种 UI 组件库的整合。
  • 此外,它还支持与各种 UI 组件库的整合。

佐德

  • 一个以 TypeScript 为主的验证库,用于创建详细的、可重用的验证模式(schema)。
  • 与 TypeScript 类型集成,从而保持验证统一并避免重复。

Shadcn/UI

  • 提供一系列可重用的UI组件,直接嵌入项目,让开发人员能够按需选择和自定义这些组件。
  • 内置React Hook Form和Zod的支持。

下面是一个示例代码片段,展示了 Shadcn 库中的一个表单字段:

    <FormField
      control={form.control}
      name="name"
      render={({ field }) => (
        <FormItem>
          <FormLabel>姓名</FormLabel>
          <FormControl>
            <Input {...field} />
          </FormControl>
          <FormMessage />
        </FormItem>
      )}
    />

全屏模式 退出全屏

即使你喜欢使用不同的技术栈,只要你坚持使用React和RHF,这仍然是一个有效的示例,可以帮助你入门。

我们来建一个简单的用户仪表板

我们将用来演示基本表单的应用是一个具有基本 CRUD 操作的管理员面板。该面板将包括电子邮件和密码认证,并包含两个页面:一个显示所有用户表格的主屏幕,以及一个用户创建页面,这将是本文的亮点。

这是一个例子样例

一个表单示例

我们的表单将包括验证,以确保用户在未满足指定要求的情况下无法提交表单(即,创建新用户)。User 对象是验证示例的绝佳候选对象,因为它包含适合不同类型验证的各种数据类型:字符串、日期(如出生日期)、电子邮件地址和布尔值(如付费用户状态)。完整的 Prisma 架构文件如下所示。

    定义 Customer {
      id    Int    @id @default(autoincrement())
      name  String
      surname String
      email String
      dateOfBirth 日期时间
      premiumUser 高级用户
    }

全屏查看 退出全屏

为了启动我们的项目,我们将使用一个预定义的Wasp模板,带有TypeScript,名为todo-ts。此模板包含现成的组件和路由,专门用于身份验证,包括登录和注册屏幕。它还提供了一个很好的示例,展示如何在Wasp中执行CRUD操作,非常适合新手。此外,我们还将使用新的Wasp TypeScript SDK来管理配置,这为我们提供了更多的自定义选项。

你觉得这篇文章有用吗?

Wasp团队正在努力创作这样的内容,比如,更别提构建一个现代的开源React/NodeJS框架。

给 Wasp 仓库点个星✨就是最简单的方式!但是如果你能花点时间查看一下 仓库(无论是为了贡献还是测试产品),我们会非常感谢。点击下面的按钮给 Wasp 点个星,表达你的支持吧!

此处无文本。图片说明

⭐️ 感谢大家的支持 💪

把这一切整合起来 - Zod 方案 + React Hook Form 实例使用 + 布局设计

为了处理表单的过程,我们将从定义一个 Zod 验证模式开始。我们的表单有三种数据类型:字符串、日期和布尔类型。我们将验证大多数字段:namesurname 是必填项,而 email 场景则使用内置的电子邮件验证。Zod 通过其内置的验证(如电子邮件、URL 和 UUID 等)简化了常见字符串类型的验证,这对我们的电子邮件字段特别有用。

对于额外的验证要求,日期不能设置为未来的日期,也就是说不能比当前时间更晚。而premiumUser字段只需要是一个布尔值。Zod还提供了默认的验证错误消息,但这些消息可以被自定义。例如,我们可以将name: z.string().min(1)改为name: z.string().min(1, 'Name is required.')

      const formSchema = z.object({
        name: z.string().min(1, { message: '请输入姓名' }),
        surname: z.string().min(1, { message: '请输入姓氏' }),
        email: z.string().email({ message: '无效的电子邮件地址' }),
        dateOfBirth: z.date().max(new Date(), { message: '日期不能是未来的日期' }),
        premiumUser: z.boolean(),
      });

请点击这里进入全屏查看,点击这里退出全屏查看。

我们的表单由来自React Hook FormuseForm钩子管理,它提供了处理和验证表单数据、检查错误和管理表单状态的多种选择。为了集成我们的Zod验证方案,我们将使用一个Zod解析器,让React Hook Form应用我们前面定义的验证规则。

表单的defaultValues是从客户对象中提取的。由于此组件既用于添加新客户也用于编辑现有客户,我们将所需的数据作为输入。对于新客户,使用一些合适的默认值;对于现有客户,则从数据库获取数据。除了设置默认值和决定调用createCustomerupdateCustomer之外,表单处理的其他方面保持一致。

    type 表单数据类型 = z.infer<typeof 表单模式>
    const 表单 = useForm<表单数据类型>({
      解构器: zodResolver(表单模式),
      默认值: 客户数据,
    });

全屏 退出

最后一步是创建表单本身,并将其嵌入到TSX文件中。正如之前所说,这个过程相当简单。不论是使用文本输入框、日期选择器还是带有Shadcn控件的复选框,我们都会遵循相似的结构。

  • 首先,创建 FormField 元素,并设置 FormFieldcontrolnamerender 属性。
  • render 属性非常重要,因为它包含了实际的表单元素。
  • 通常我们会用 FormItem 包裹所有内容,添加一个 FormLabel 作为标签,并将受控表单元素放在 FormControl 中,同时设置相应的值和回调函数。
  • 最后,在下方加上 FormMessage,以显示 Zod 验证失败的消息。

有错误的表单

    // 定义表单架构
    const formSchema = z.object({   
        dateOfBirth: z.date().max(new Date(), {
          message: '出生日期不能是今日或未来',
        }),    
    });

    // 定义表单  
    const form = useForm<FormData>({
        resolver: zodResolver(formSchema),
        defaultValues: defaultValues,
    });

    // 创建表单控件
      <FormField
      control={form.control}
      name="dateOfBirth"
      render={({ field }) => (
        <FormItem className="flex flex-col">
          <FormLabel>出生日期</FormLabel>
          <FormControl>
            <DatePicker date={field.value} setDate={field.onChange} />
          </FormControl>
          <FormMessage />
        </FormItem>
      )}
    />

全屏显示,切换回正常显示

如果你好奇完整应用的样子,可以在这里看一下GitHub仓库:GitHub 仓库。希望这篇文章能帮你更轻松地处理表单,如果你对更多关于表单的内容感兴趣,敬请关注第二部分!在接下来的部分中,我们将深入探讨一些高级模式和验证技术,让你的应用更上一层楼。

如果喜欢这篇帖子,请在GitHub上给 Wasp 点赞!你的支持对我们很有帮助,可以让我们继续让每个人都能更轻松地开发 web。🐝

点击查看更多内容
1人点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消