nextjs 使用react-hook-form和zod实现登录表单验证和提交
背景说明
nextjs 使用中不可避免地会碰到使用表单,尤其是登录表单。而对于提交表单来说要关注的几个要素就是数据收集、数据校验和数据提交(涉及异步操作)。本文将围绕这几个要素,并通过zod和react-hook-form提供的能力实现登录表单。
本文所述依赖如下的库包及其版本
包名 | 版本号 |
---|---|
next | 14.2.15 |
react | 18.2.0 |
react-dom | 18.2.0 |
zod | 3.24.1 |
react-hook-form | 7.54.2 |
@hookform/resolvers | 3.9.1 |
本文的开发环境基于 Macbook Pro M1 MacOS 14.6.1。
zod 简单上手
zod 提供了简单的表单校验器,且支持typescript,并弥补了typescrip对运行时代码无法校验的不足,通过一次定义,不仅可以通过safeParse方法验证表单数据,导出错误,还可以通过z.infer推断表单模型的typescript类型。
下载
1 | pnpm add zod |
以邮箱登录表单为例
1 | export const loginSchema = z.object({ |
可以看到,我们可以使用z.object()
定义模型,通过schema.safeParse()
方法返回的对象resp
。
通过resp.success
可以判断数据是否校验成功,一旦校验成功则通过resp.data
获取输入的表单数据,否则可以使用resp.error
获取校验错误。
登录表单的UI实现
由于css样式比较繁琐,这里使用shadcn ui这个组件库+Tailwindcss。其中有邮箱和密码的输入框还有一个用于提交表单的按钮。
1 | export default function LoginForm() { |
使用 react-hook-form
基本使用
react-hook-form 提供了许多用于表单的hook,在这使用的是useForm
这个hook。
基本用法如下:
1 | import {useForm} from "react-hook-form" |
可以看到useForm
导出了三个方法和一个对象,其中最为重要的当属handleSubmit
和register
方法,一个用来注册某些原生属性或者事件以及校验规则。对于校验规则,其提供了一个resolver属性允许使用第三方的表单校验库去完成。
1 | import { zodResolver } from "@hookform/resolvers/zod"; |
对此,我们可以使用上节提到的zod来实现表单校验,通过安装@hookform/resolvers导入zodResolver
,传入上节定义号的表单校验模型。
ts智能提示
再通过useForm
传入zod
推断的数据类型,可以在使用register方法时得到更好的智能提示。
1 | type LoginData = z.infer<typeof loginSchema> |
获取错误并修改表单样式
当表单校验发生错误时,常见的UI提示是输入框边框转为警告色,并在其下方显示对应的错误信息,就像下述这样,当邮箱地址格式错误显示错误的信息:
该错误信息在使用zod
时已定义:
警告色样式可由tailwindcss提供:
但如何知道字段校验错误,并取出这些错误提示信息呢。答案是上文导出的errors属性。
1 | const {formState:{errors}} = useForm() |
导出errors属性,其也是一个对象,可通过errors.[field].message
取出错误信息
1 | console.log(errors.email.message) \\邮箱地址格式错误 |
可以使用一个p标签显示信息
1 | <form> |
至此,实现了字段校验错误信息的显示和UI的警告色功能。
表单提交时按钮禁用
当表单在提交时往往是异步状态,在提交结束前我们往往期望暂时禁用提交按钮,直到本次提交完成(无论成功与否)。
在当前的示例中,点击登录按钮,按钮立刻处于禁用样式其文字页变更为【登录中…】,很容易想到需要一个布尔值在表单提交时设置为true添加到button
的disabled
属性和实现添加渲染不同的按钮文字。
幸运地是,useForm
提供了这个属性,我们可以像得到errors
对象属性一样,拿到这个布尔属性isSubmitting
。
1 | const { |
到这,按钮提交时禁用也实现了。
当本示例的登录表单完成校验后将会触发form
元素的提交事件,执行在handleSubmit
中传入的回调函数:
本文小结
本文通过登录表单的案例,介绍了如何使用zod
和react-hook-form
实现表单数据收集和校验的全过程和数据校验,并补充了一些需要的注意事项。