Logo
React Hooks Form
所属分类:开发日常
阅读量:43
评论数量:0
发布时间:2024-09-12 08:19

image.png

React Hooks Form

react-hook-form 是一个专注于管理 React 表单状态的库。它的核心理念是利用 React Hooks 来简化表单的处理过程。与其他表单管理库相比,它的优势在于性能和简洁性。它不需要在每次输入更改时重新渲染整个表单组件,从而提高了性能。

其实最主要的原因是有很多组件库并没有提供表单校验功能,而且每个组件库的表单校验功能用法都不一致,因此我选择使用 react-hook-form 这样在使用不同组件库时表单的校验方式完成了统一。

下面我来介绍一下这个表单校验库:

安装

npm install react-hook-form

官方快速入门教程: Get Started (react-hook-form.com)

Register

用于注册表单字段使表单能够监听到该字段的数据

import { useState } from "react";
import { SubmitHandler, useForm } from "react-hook-form";

interface FormData {
    name: string;
    age: number;
}

export default () => {
    const [defaultValues, setDefaultValues] = useState({ name: "", age: 0 })
    const { register, handleSubmit } = useForm<FormData>({ defaultValues });
    const onSubmit: SubmitHandler<FormData> = (data, event) => {
        // 阻止默认提交行为
        event?.preventDefault();

        console.log(data)
        // {name: 'yuyang', age: '21'}
    }

    return (
        <>
            <form onSubmit={handleSubmit(onSubmit)}>
                <input {...register("name")} type="text" />
                <input {...register("age")} type="text" />

                <button type="submit">提交</button>
            </form>
        </>
    )
}

约束表单数据

<form onSubmit={handleSubmit(onSubmit)}>
    <input {...register("name", { required: true, maxLength: 3 })} type="text" />
    <input {...register("age", { min: 0, max: 99 })} type="text" />

		<button type="submit">提交</button>
</form>

当然也可以使用正则

<input {...register("age", { pattern: /^(0|[1-9][0-9]?)$/ })} type="text" />

显示错误信息

const { register, handleSubmit, formState: { errors } } = useForm<FormData>({ defaultValues });
<form onSubmit={handleSubmit(onSubmit)}>
    <input
        {...register("name",
            {
                required: { value: true, message: "请输入名称" },
                maxLength: { value: 3, message: "名称不符合长度" }
            })}
        type="text"
    />
    <span>{errors.name && errors.name.message}</span>

    <input {...register("age", { pattern: { value: /^(0|[1-9][0-9]?)$/, message: "输入的年龄错误" } })} type="text" />
    <span>{errors.age && errors.age.message}</span>

    <button type="submit">提交</button>
</form>

重置表单数据

reset 它的作用是重置表单 defaultValues 初始数据,我们一般用于获取接口数据后,将数据回显给表单

const [ defaultValues, setDefaultValues ] = useState({ name: "", age: 0 })
const { register, handleSubmit, reset } = useForm<FormData>({ defaultValues });

示例: 1 秒钟后将数据更改

useEffect(() => {
    setTimeout(() => {
      	// 错误:如果我们直接修改它的值,实际上确实可以修改,不过数据虽然更改了但表单数据还是之前的并不会同步
  			// setDefaultValues({ name: "yuyang", age: 21 })
      
      	// 所以可以使用 reset 来重置默认数据实现回显效果
        reset({ name: "宇阳", age: 21 })
    }, 1000)
}, [])

手动触发表单验证

通过 trigger 可以实现手动触发表单的验证,通常适用于表单失去焦点时验证表单

const { register, handleSubmit, formState: { errors }, trigger } = useForm<FormData>({ defaultValues });
<input
    {...register("name", { required: { value: true, message: "请输入名称" } })}
    type="text"
    onBlur={() => { trigger('name') }}
/>
<span>{errors.name && errors.name?.message}</span>

监听表单数据变化

通过 watch 可以监听表单某一项或整个表单的数据变化

const { register, handleSubmit, watch } = useForm<FormData>({ defaultValues });
// 监听单个数据的变化
const data = watch("name");
// const data = watch("name", "宇阳"); // 默认值
// 宇阳

// 监听多个数据的变化
// const data = watch(["name", "age"]);
// ["宇阳", "21"]

// 监听表单所有数据的变化
// const data = watch();
// { name: '宇阳', age: '21' }

useEffect(() => {
    console.log(data);
}, [data])
<form onSubmit={handleSubmit(onSubmit)}>
    <input {...register("name")} type="text" />
    <input {...register("age")} type="text" />

    <button type="submit">提交</button>
</form>

自定义行为

默认情况下 react hooks form 自动帮我们对 value onChange 等操作做了处理,所以我们可以不用写他们。

但有些场合,比如说我们需要对输入的值做一些处理,那么我们可以自定义 onChange

但需要注意的是需要手动调用一下 register("age").onChange(e),否则这个表单就失去了 react hooks form 的特性

<form onSubmit={handleSubmit(onSubmit)}>
    <input {...register("name")} type="text" />
    <input {...register("age")} type="text" onChange={(e) => {
        // 在这里做一些自定义的操作
        console.log(e.target.value);

        // 但一定不要忘记 调用 onChange
        register("age").onChange(e)
    }} />

    <button type="submit">提交</button>
</form>

其他 API

这些比较有用,但过于简单,就不必展开细说了,大家可以查阅官方文档

获取表单焦点

参考: https://react-hook-form.com/docs/useform/setfocus

获取表单的值

参考: https://react-hook-form.com/docs/useform/getvalues

操作表单的值

参考: https://react-hook-form.com/docs/useform/setvalue

清除表单验证的错误

参考: https://react-hook-form.com/docs/useform/clearerrors

Controller(推荐)

它的功能与 Register 类似,都是用于注册表单的字段 并且 RegisterAPI 都可以使用。但不同的是该方式时候于第三方组件库使用,因为有些组件库可能并没有提供 valueonChange 或者属性名不一致导致使用 Register 会有些问题。

所以该方式适用于第三方组件库。如果组件库具有 valueonChange 那么使用Register也是可行的,不过最好使用 Controller 方式。下面将演示一下它的使用:

import { Input } from "@nextui-org/react";
import { useState } from "react";
import { Controller, SubmitHandler, useForm } from "react-hook-form";

interface FormData {
    name: string;
    age: number;
}

export default () => {
    const [defaultValues, setDefaultValues] = useState({ name: "", age: 0 })
    const { register, handleSubmit, control, formState: { errors }, trigger } = useForm<FormData>({ defaultValues });
    const onSubmit: SubmitHandler<FormData> = (data, event) => {
        // 阻止默认提交行为
        event?.preventDefault();

        console.log(data)
        // {name: 'yuyang', age: '21'}
    }

    return (
        <>
            <form onSubmit={handleSubmit(onSubmit)}>
                <Controller
                    name="name"
                    control={control}
                    rules={{ required: '请输入名称' }}
                    render={({ field }) => (
                        <>
                            <Input {...field} type="text" onChange={(e) => {
                                // 自定义行为
                                console.log(e.target.value);

                                // 务必调用 onChange
                                field.onChange(e)
                            }} onBlur={() => trigger('name')} />
                            <span>{errors.name && errors.name?.message}</span>
                        </>
                    )}
                />

                {/* 两种方式也可以混合使用 */}
                <input {...register("age")} type="text" />

                <button type="submit">提交</button>
            </form>
        </>
    )
}

总结:

虽然很明确组件库具有 valueonChangeRegister 也可以使用 或者 Controller 也可以直接使用原生表单。但还是有必要区分一下

Register: 用于简单的原生表单

Controller: 用于复杂的第三方组件表单

image.png

作者:宇阳

版权:此文章版权归 宇阳 所有,如有转载,请注明出处!

空状态
评论列表为空~
目录
作者头像

一直对网站开发领域很感兴趣,从小就希望有一个属于自己的网站,在17年时候成功进入站长圈,并通过各种自学,以及各种折腾,才有了你现在看到的这个网站

月亮搜索返回顶部