每个开发者都会遇到表单,无论是作为用户还是开发者。表单在大多数网站上都很重要,但它们的复杂度差异很大——从简单的三字段联系表单到复杂的多页表单,包含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 验证模式开始。我们的表单有三种数据类型:字符串、日期和布尔类型。我们将验证大多数字段:name
和 surname
是必填项,而 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 Form的useForm
钩子管理,它提供了处理和验证表单数据、检查错误和管理表单状态的多种选择。为了集成我们的Zod验证方案,我们将使用一个Zod解析器,让React Hook Form应用我们前面定义的验证规则。
表单的defaultValues
是从客户对象中提取的。由于此组件既用于添加新客户也用于编辑现有客户,我们将所需的数据作为输入。对于新客户,使用一些合适的默认值;对于现有客户,则从数据库获取数据。除了设置默认值和决定调用createCustomer
或updateCustomer
之外,表单处理的其他方面保持一致。
type 表单数据类型 = z.infer<typeof 表单模式>
const 表单 = useForm<表单数据类型>({
解构器: zodResolver(表单模式),
默认值: 客户数据,
});
全屏 退出
最后一步是创建表单本身,并将其嵌入到TSX文件中。正如之前所说,这个过程相当简单。不论是使用文本输入框、日期选择器还是带有Shadcn控件的复选框,我们都会遵循相似的结构。
- 首先,创建
FormField
元素,并设置FormField
的control
、name
和render
属性。 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。🐝
共同学习,写下你的评论
评论加载中...
作者其他优质文章