React Hook Form (RHF) 详细介绍

December 6, 2024

React Hook Form (RHF) 是一个用于构建 React 表单的轻量级库,其核心目标是简化表单的状态管理和验证,同时提高性能。以下是对 React Hook Form 的详细介绍,包括其特点、基本用法以及进阶功能。

1. React Hook Form 的核心特点

  1. 轻量高效

    • 基于非受控组件设计,减少了组件的重新渲染。
    • 与受控组件相比,大幅降低性能消耗。
  2. 简单易用

    • 基于 React Hooks,无需引入复杂的上下文或状态管理。
  3. 灵活验证

    • 内置多种验证机制,并支持与验证库(如 Yup)集成。
  4. 类型安全

    • 提供 TypeScript 支持,确保表单类型安全。

2. 核心 API

2.1. useForm

useForm 是 RHF 的核心钩子,用于管理表单状态。

常用配置选项

  • defaultValues:设置初始值。
  • mode:验证触发模式(如 onChange, onBlur, onSubmit)。
  • resolver:用于集成外部验证库(如 Yup)。

示例


  import { useForm } from 'react-hook-form';

  function App() {
    const { register, handleSubmit, watch, formState: { errors } } = useForm();

    const onSubmit = (data) => {
      console.log(data);
    };

    return (
      <form onSubmit={handleSubmit(onSubmit)}>
        <input {...register("username", { required: true })} placeholder="Username" />
        {errors.username && <span>Username is required</span>}

        <input type="submit" />
      </form>
    );
  }


2.2. register

  • 用于将输入元素注册到 RHF。
  • 接收字段名称和校验规则。

常见校验规则

  • required:是否为必填字段。
  • minLength / maxLength:最小/最大字符长度。
  • pattern:正则表达式验证。

示例


  <input 
    {...register("password", { 
      required: "Password is required", 
      minLength: { value: 6, message: "Password must be at least 6 characters" } 
    })} 
  />


2.3. handleSubmit

  • 包装提交函数,用于在表单验证通过后调用回调。
  • 自动拦截无效数据。

示例


  const onSubmit = (data) => {
    console.log("Valid Data:", data);
  };

  <form onSubmit={handleSubmit(onSubmit)} />


2.4. formState

包含表单状态信息,例如:

  • errors: 当前表单的验证错误。
  • isSubmitting: 表单是否正在提交。
  • isDirty: 表单值是否被修改。

2.5. watch

  • 实时监控表单字段值的变化。
  • 可以监控单个字段或整个表单。

示例


  const username = watch("username");


2.6. resetsetValue

  • reset: 重置表单为默认值或指定值。
  • setValue: 手动设置表单字段值。

示例


  reset({ username: "JohnDoe" });
  setValue("email", "john@example.com");


3. 基本用法

3.1. 简单表单


  import React from 'react';
  import { useForm } from 'react-hook-form';

  function SimpleForm() {
    const { register, handleSubmit, formState: { errors } } = useForm();

    const onSubmit = (data) => {
      console.log(data);
    };

    return (
      <form onSubmit={handleSubmit(onSubmit)}>
        <input {...register("name", { required: true })} placeholder="Name" />
        {errors.name && <span>Name is required</span>}

        <input type="email" {...register("email", { required: true })} placeholder="Email" />
        {errors.email && <span>Email is required</span>}

        <button type="submit">Submit</button>
      </form>
    );
  }

  export default SimpleForm;


4. 进阶功能

4.1. 默认值

通过 useFormdefaultValues 设置表单的初始值。


  const { register, handleSubmit } = useForm({
    defaultValues: {
      name: "John Doe",
      email: "john@example.com",
    }
  });


4.2. 集成 Yup 进行验证

通过 @hookform/resolvers 将 Yup 集成到 RHF。


  npm install @hookform/resolvers yup

示例


  import { useForm } from 'react-hook-form';
  import { yupResolver } from '@hookform/resolvers/yup';
  import * as Yup from 'yup';

  const schema = Yup.object().shape({
    username: Yup.string().required("Username is required"),
    email: Yup.string().email("Invalid email").required("Email is required"),
  });

  function App() {
    const { register, handleSubmit, formState: { errors } } = useForm({
      resolver: yupResolver(schema),
    });

    const onSubmit = (data) => console.log(data);

    return (
      <form onSubmit={handleSubmit(onSubmit)}>
        <input {...register("username")} placeholder="Username" />
        {errors.username && <span>{errors.username.message}</span>}

        <input {...register("email")} placeholder="Email" />
        {errors.email && <span>{errors.email.message}</span>}

        <button type="submit">Submit</button>
      </form>
    );
  }


4.3. 动态表单

动态添加或删除字段。


  import React, { useState } from 'react';
  import { useForm } from 'react-hook-form';

  function DynamicForm() {
    const { register, handleSubmit } = useForm();
    const [fields, setFields] = useState([{}]);

    const addField = () => setFields([...fields, {}]);

    const onSubmit = (data) => console.log(data);

    return (
      <form onSubmit={handleSubmit(onSubmit)}>
        {fields.map((_, index) => (
          <input key={index} {...register(`field${index}`)} placeholder={`Field ${index + 1}`} />
        ))}
        <button type="button" onClick={addField}>Add Field</button>
        <button type="submit">Submit</button>
      </form>
    );
  }


4.4. 与 UI 库集成

与 Material-UI、Ant Design 等库集成。

示例:Ant Design Input


  import { Controller, useForm } from 'react-hook-form';
  import { Input } from 'antd';

  function AntdForm() {
    const { control, handleSubmit } = useForm();

    const onSubmit = (data) => console.log(data);

    return (
      <form onSubmit={handleSubmit(onSubmit)}>
        <Controller
          name="username"
          control={control}
          render={({ field }) => <Input {...field} placeholder="Username" />}
        />
        <button type="submit">Submit</button>
      </form>
    );
  }


5. 性能优化

  • 默认优化:非受控组件减少了组件重新渲染。
  • useController:对复杂场景提供更细粒度的控制。
  • 惰性验证:只验证用户已触摸的字段,减少性能开销。

6. 常见场景与解决方案

  1. 多步骤表单:通过保存每步数据到状态中实现。
  2. 条件渲染字段:根据条件动态添加/删除字段。
  3. 文件上传:通过 ref 获取文件输入并处理。

React Hook Form 提供了强大的功能和高效的性能,是构建现代 React 表单的首选工具之一。

React Hook Form (RHF) 详细介绍