安装
安装 React Hook Form 只需一条命令,你就可以开始使用了。
npm install react-hook-form
示例
以下代码片段演示了基本用法示例
import { useForm, SubmitHandler } from "react-hook-form"type Inputs = {example: stringexampleRequired: string}export default function App() {const {register,handleSubmit,watch,formState: { errors },} = useForm<Inputs>()const onSubmit: SubmitHandler<Inputs> = (data) => console.log(data)console.log(watch("example")) // watch input value by passing the name of itreturn (/* "handleSubmit" will validate your inputs before invoking "onSubmit" */<form onSubmit={handleSubmit(onSubmit)}>{/* register your input into the hook by invoking the "register" function */}<input defaultValue="test" {...register("example")} />{/* include validation with required or other standard HTML validation rules */}<input {...register("exampleRequired", { required: true })} />{/* errors will return when field validation fails */}{errors.exampleRequired && <span>This field is required</span>}<input type="submit" /></form>)}
React Web 视频教程
本视频教程演示了 React Hook Form 的基本用法和概念。
注册字段
React Hook Form 的关键概念之一是将你的组件注册
到钩子中。这将使它的值可用于表单验证和提交。
注意:每个字段都需要有一个name
作为注册过程的键。
import ReactDOM from "react-dom"import { useForm, SubmitHandler } from "react-hook-form"enum GenderEnum {female = "female",male = "male",other = "other",}interface IFormInput {firstName: stringgender: GenderEnum}export default function App() {const { register, handleSubmit } = useForm<IFormInput>()const onSubmit: SubmitHandler<IFormInput> = (data) => console.log(data)return (<form onSubmit={handleSubmit(onSubmit)}><label>First Name</label><input {...register("firstName")} /><label>Gender Selection</label><select {...register("gender")}><option value="female">female</option><option value="male">male</option><option value="other">other</option></select><input type="submit" /></form>)}
应用验证
React Hook Form 通过与现有的HTML 表单验证标准保持一致,使表单验证变得简单。
支持的验证规则列表
- required
- min
- max
- minLength
- maxLength
- pattern
- validate
你可以在注册部分中阅读有关每个规则的更多详细信息。
import { useForm, SubmitHandler } from "react-hook-form"interface IFormInput {firstName: stringlastName: stringage: number}export default function App() {const { register, handleSubmit } = useForm<IFormInput>()const onSubmit: SubmitHandler<IFormInput> = (data) => console.log(data)return (<form onSubmit={handleSubmit(onSubmit)}><input {...register("firstName", { required: true, maxLength: 20 })} /><input {...register("lastName", { pattern: /^[A-Za-z]+$/i })} /><input type="number" {...register("age", { min: 18, max: 99 })} /><input type="submit" /></form>)}
集成现有表单
集成现有表单应该很简单。重要的步骤是注册
组件的ref
并为你的输入分配相关的属性。
import { Path, useForm, UseFormRegister, SubmitHandler } from "react-hook-form"interface IFormValues {"First Name": stringAge: number}type InputProps = {label: Path<IFormValues>register: UseFormRegister<IFormValues>required: boolean}// The following component is an example of your existing Input Componentconst Input = ({ label, register, required }: InputProps) => (<><label>{label}</label><input {...register(label, { required })} /></>)// you can use React.forwardRef to pass the ref tooconst Select = React.forwardRef<HTMLSelectElement,{ label: string } & ReturnType<UseFormRegister<IFormValues>>>(({ onChange, onBlur, name, label }, ref) => (<><label>{label}</label><select name={name} ref={ref} onChange={onChange} onBlur={onBlur}><option value="20">20</option><option value="30">30</option></select></>))const App = () => {const { register, handleSubmit } = useForm<IFormValues>()const onSubmit: SubmitHandler<IFormValues> = (data) => {alert(JSON.stringify(data))}return (<form onSubmit={handleSubmit(onSubmit)}><Input label="First Name" register={register} required /><Select label="Age" {...register("Age")} /><input type="submit" /></form>)}
与 UI 库集成
React Hook Form 使得与外部 UI 组件库集成变得容易。如果组件没有公开输入的ref
,那么你应该使用Controller组件,它将负责注册过程。
import Select from "react-select"import { useForm, Controller, SubmitHandler } from "react-hook-form"import { Input } from "@material-ui/core"interface IFormInput {firstName: stringlastName: stringiceCreamType: { label: string; value: string }}const App = () => {const { control, handleSubmit } = useForm({defaultValues: {firstName: "",lastName: "",iceCreamType: {},},})const onSubmit: SubmitHandler<IFormInput> = (data) => {console.log(data)}return (<form onSubmit={handleSubmit(onSubmit)}><Controllername="firstName"control={control}render={({ field }) => <Input {...field} />}/><Controllername="iceCreamType"control={control}render={({ field }) => (<Select{...field}options={[{ value: "chocolate", label: "Chocolate" },{ value: "strawberry", label: "Strawberry" },{ value: "vanilla", label: "Vanilla" },]}/>)}/><input type="submit" /></form>)}
集成受控输入
这个库采用不受控组件和原生 HTML 输入。但是,很难避免使用外部受控组件,例如React-Select、AntD和MUI。为了简化这个过程,我们提供了一个包装器组件Controller,以简化集成过程,同时仍然让你能够使用自定义注册。
使用组件 API
import { useForm, Controller, SubmitHandler } from "react-hook-form"import { TextField, Checkbox } from "@material-ui/core"interface IFormInputs {TextField: stringMyCheckbox: boolean}function App() {const { handleSubmit, control, reset } = useForm<IFormInputs>({defaultValues: {MyCheckbox: false,},})const onSubmit: SubmitHandler<IFormInputs> = (data) => console.log(data)return (<form onSubmit={handleSubmit(onSubmit)}><Controllername="MyCheckbox"control={control}rules={{ required: true }}render={({ field }) => <Checkbox {...field} />}/><input type="submit" /></form>)}
使用钩子 API
import * as React from "react"import { useForm, useController, UseControllerProps } from "react-hook-form"type FormValues = {FirstName: string}function Input(props: UseControllerProps<FormValues>) {const { field, fieldState } = useController(props)return (<div><input {...field} placeholder={props.name} /><p>{fieldState.isTouched && "Touched"}</p><p>{fieldState.isDirty && "Dirty"}</p><p>{fieldState.invalid ? "invalid" : "valid"}</p></div>)}export default function App() {const { handleSubmit, control } = useForm<FormValues>({defaultValues: {FirstName: "",},mode: "onChange",})const onSubmit = (data: FormValues) => console.log(data)return (<form onSubmit={handleSubmit(onSubmit)}><Input control={control} name="FirstName" rules={{ required: true }} /><input type="submit" /></form>)}
与全局状态集成
这个库不需要你依赖于状态管理库,但你可以轻松地与它们集成。
import { useForm } from "react-hook-form"import { connect } from "react-redux"import updateAction from "./actions"export default function App(props) {const { register, handleSubmit, setValue } = useForm({defaultValues: {firstName: "",lastName: "",},})// Submit your data into Redux storeconst onSubmit = (data) => props.updateAction(data)return (<form onSubmit={handleSubmit(onSubmit)}><input {...register("firstName")} /><input {...register("lastName")} /><input type="submit" /></form>)}// Connect your component with reduxconnect(({ firstName, lastName }) => ({ firstName, lastName }),updateAction)(YourForm)
处理错误
React Hook Form 提供一个errors
对象来显示表单中的错误。errors
的类型将返回给定的验证约束。以下示例展示了一个必需的验证规则。
import { useForm } from "react-hook-form"export default function App() {const {register,formState: { errors },handleSubmit,} = useForm()const onSubmit = (data) => console.log(data)return (<form onSubmit={handleSubmit(onSubmit)}><input{...register("firstName", { required: true })}aria-invalid={errors.firstName ? "true" : "false"}/>{errors.firstName?.type === "required" && (<p role="alert">First name is required</p>)}<input{...register("mail", { required: "Email Address is required" })}aria-invalid={errors.mail ? "true" : "false"}/>{errors.mail && <p role="alert">{errors.mail.message}</p>}<input type="submit" /></form>)}
与服务集成
要将 React Hook Form 与服务集成,你可以使用库的内置提交处理。<Form />
组件允许你轻松地将表单数据发送到 API 端点或其他服务。详细了解 Form 组件.
import { Form } from "react-hook-form"function App() {const { register, control } = useForm()return (<Formaction="/api/save" // Send post request with the FormData// encType={'application/json'} you can also switch to json objectonSuccess={() => {alert("Your application is updated.")}}onError={() => {alert("Submission has failed.")}}control={control}><input {...register("firstName", { required: true })} /><input {...register("lastName", { required: true })} /><button>Submit</button></Form>)}
模式验证
我们还支持使用Yup、Zod、Superstruct和Joi的基于模式的表单验证,你可以在其中将你的schema
传递给useForm作为可选配置。它将根据模式验证你的输入数据,并返回errors或有效结果。
步骤 1:将Yup
安装到你的项目中。
npm install @hookform/resolvers yup
步骤 2:准备你的验证模式并使用 React Hook Form 注册输入。
import { useForm } from "react-hook-form"import { yupResolver } from "@hookform/resolvers/yup"import * as yup from "yup"const schema = yup.object({firstName: yup.string().required(),age: yup.number().positive().integer().required(),}).required()export default function App() {const {register,handleSubmit,formState: { errors },} = useForm({resolver: yupResolver(schema),})const onSubmit = (data) => console.log(data)return (<form onSubmit={handleSubmit(onSubmit)}><input {...register("firstName")} /><p>{errors.firstName?.message}</p><input {...register("age")} /><p>{errors.age?.message}</p><input type="submit" /></form>)}
React Native
你将在 React Native 中获得相同的性能提升和增强。要与输入组件集成,你可以用Controller
包装它。
import { Text, View, TextInput, Button, Alert } from "react-native"import { useForm, Controller } from "react-hook-form"export default function App() {const {control,handleSubmit,formState: { errors },} = useForm({defaultValues: {firstName: "",lastName: "",},})const onSubmit = (data) => console.log(data)return (<View><Controllercontrol={control}rules={{required: true,}}render={({ field: { onChange, onBlur, value } }) => (<TextInputplaceholder="First name"onBlur={onBlur}onChangeText={onChange}value={value}/>)}name="firstName"/>{errors.firstName && <Text>This is required.</Text>}<Controllercontrol={control}rules={{maxLength: 100,}}render={({ field: { onChange, onBlur, value } }) => (<TextInputplaceholder="Last name"onBlur={onBlur}onChangeText={onChange}value={value}/>)}name="lastName"/><Button title="Submit" onPress={handleSubmit(onSubmit)} /></View>)}
TypeScript
React Hook Form 是用TypeScript
构建的,你可以定义一个FormData
类型来支持表单值。
import * as React from "react"import { useForm } from "react-hook-form"type FormData = {firstName: stringlastName: string}export default function App() {const {register,setValue,handleSubmit,formState: { errors },} = useForm<FormData>()const onSubmit = handleSubmit((data) => console.log(data))// firstName and lastName will have correct typereturn (<form onSubmit={onSubmit}><label>First Name</label><input {...register("firstName")} /><label>Last Name</label><input {...register("lastName")} /><buttontype="button"onClick={() => {setValue("lastName", "luo") // ✅setValue("firstName", true) // ❌: true is not stringerrors.bill // ❌: property bill does not exist}}>SetValue</button></form>)}
设计与理念
React Hook Form 的设计和理念侧重于用户和开发者体验。该库旨在通过微调性能和改进可访问性,为用户提供更流畅的交互体验。一些性能增强包括
- 通过代理引入表单状态订阅模型
- 避免不必要的计算
- 在需要时隔离组件重新渲染
总的来说,它在用户与应用程序交互时改善了用户体验。对于开发者,我们引入了内置验证,并与 HTML 标准紧密结合,允许使用强大的验证方法进行扩展,并原生集成模式验证。此外,借助 typescript,具有强类型检查的表单可以提供早期的构建时反馈,帮助和引导开发者构建强大的表单解决方案。
以下由Bill发表的演讲展示了一些想法和设计模式
感谢您的支持
如果您发现 React Hook Form 对您的项目有用,请考虑为它加星并支持它。