发布于 2026-01-06 0 阅读
0

React DEV 全球展示挑战赛,Mux 倾情呈现:展示你的项目!

React 中创建简单和复杂表单的最佳库

由 Mux 主办的 DEV 全球展示挑战赛:展示你的项目!

在 React 中创建表单是一项复杂的任务。它涉及处理所有输入状态及其变化,并在表单提交时验证输入内容。

对于简单的表单,通常比较容易管理。但随着表单变得越来越复杂,需要添加各种验证,任务就变得很繁琐了。

因此,与其手动编写所有代码并处理带有验证逻辑的复杂表单,我们可以使用最流行的 React 库react-hook-form来实现这一点。

与FormikReact Final Form等相比,它是最流行的 React 表单创建库,我将其用于我所有的客户项目。

本文将详细介绍如何使用react-hook-form库。

那么,我们开始吧。

为什么 react-hook-form 库是 React 中最受欢迎的表单库

以下是 react-hook-form 成为创建 React 表单的热门选择的一些原因。

  • 与替代方案相比,该应用程序的重新渲染次数更少,因为它使用 refs 而不是 state。
  • 与 formik、react-final-form 和其他替代方案相比,您需要编写的代码量更少。
  • react-hook-form 与 yup 库很好地集成,用于模式验证,因此您可以组合自己的验证模式。
  • 与其他替代方案相比,安装时间更短。

请访问react-hook-form网站查看更详细的比较信息。

如何在不使用库的情况下创建表单

在使用 react-hook-form 库创建表单之前,让我们先创建一个不使用任何库的简单表单。

请查看以下代码:

import React, { useState } from "react";
import "./styles.css";

export default function App() {
  const [state, setState] = useState({
    email: "",
    password: ""
  });

  const handleInputChange = (event) => {
    const { name, value } = event.target;
    setState((prevProps) => ({
      ...prevProps,
      [name]: value
    }));
  };

  const handleSubmit = (event) => {
    event.preventDefault();
    console.log(state);
  };

  return (
    <div className="App">
      <form onSubmit={handleSubmit}>
        <div className="form-control">
          <label>Email</label>
          <input
            type="text"
            name="email"
            value={state.email}
            onChange={handleInputChange}
          />
        </div>
        <div className="form-control">
          <label>Password</label>
          <input
            type="password"
            name="password"
            value={state.password}
            onChange={handleInputChange}
          />
        </div>
        <div className="form-control">
          <label></label>
          <button type="submit">Login</button>
        </div>
      </form>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

这是一个代码沙盒演示

上面的代码中只有两个输入字段,即和emailpassword以及一个提交按钮。

每个输入字段都添加了一个value处理onChange程序,以便我们可以根据用户的输入更新状态。

此外,我们还添加了一个handleSubmit方法,可以将表单中输入的数据显示在控制台中。

这样看起来没问题。但是如果我们需要添加诸如必填字段验证、最小长度验证、密码验证、电子邮件字段验证等验证,并且还需要显示相应的错误消息,该怎么办呢?

随着输入字段及其验证的数量增加,代码将变得越来越复杂和冗长。

如何安装 react-hook-form 库

在任何应用程序中,显示表单都是一项非常常见的需求。

那么,让我们来学习一下为什么要使用它以及如何使用它react-hook-form。为此,我们将创建一个新的 React 应用程序。

在终端运行以下命令,创建一个新的 React 项目:

create-react-app demo-react-hook-form
Enter fullscreen mode Exit fullscreen mode

项目创建完成后,删除文件夹中的所有文件,并在文件夹src创建新index.js文件styles.csssrc

要安装该react-hook-form库,请在终端中执行以下命令:

npm install react-hook-form@7.38.0

OR

yarn add react-hook-form@7.38.0
Enter fullscreen mode Exit fullscreen mode

在这里,我们将安装7.38.0该库的最新版本react-hook-form,该版本在撰写本文时是最新版本。

如何创建初始页面

打开src/index.js文件,并在其中添加以下内容:

import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<App />);
Enter fullscreen mode Exit fullscreen mode

请注意,以上代码使用的是 React 18+ 版本语法来渲染应用程序。

如果您使用的是 React 版本低于 18(您可以从package.json文件中确认),则将以下代码添加到您的src/index.js文件中。

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';

ReactDOM.render(<App />, document.getElementById('root'));
Enter fullscreen mode Exit fullscreen mode

现在,打开src/styles.css文件,并将这里的内容添加到文件中。

现在,在文件夹App.js内创建一个名为 `<filename>` 的新文件src,并写入以下内容:

import React from "react";
import "./styles.css";

export default function App() {
  return (
    <div className="App">
      <form>
        <div className="form-control">
          <label>Email</label>
          <input type="text" name="email" />
        </div>
        <div className="form-control">
          <label>Password</label>
          <input type="password" name="password" />
        </div>
        <div className="form-control">
          <label></label>
          <button type="submit">Login</button>
        </div>
      </form>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

这里,我们刚刚在表单中添加了电子邮件和密码字段。

如何使用 react-hook-form 创建基本表单

react-hook-form库提供了一个useForm钩子,我们可以利用它来处理表单。

useForm像这样导入钩子:

import { useForm } from 'react-hook-form';
Enter fullscreen mode Exit fullscreen mode

你可以useForm像这样使用钩子:

const {
  register,
  handleSubmit,
  formState: { errors },
} = useForm();
Enter fullscreen mode Exit fullscreen mode

这里,

  • register这是一个由钩子函数提供的函数useForm。我们可以将其分配给每个输入字段,以便react-hook-form跟踪输入字段值的变化。
  • handleSubmit这是表单提交后我们可以调用的函数。
  • errors是对象中的一个嵌套属性formState,用于存储验证错误(如果有)。

现在,将文件内容替换App.js为以下代码:

import React from "react";
import { useForm } from "react-hook-form";
import "./styles.css";

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

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

  return (
    <div className="App">
      <form onSubmit={handleSubmit(onSubmit)}>
        <div className="form-control">
          <label>Email</label>
          <input type="text" name="email" {...register("email")} />
        </div>
        <div className="form-control">
          <label>Password</label>
          <input type="password" name="password" {...register("password")} />
        </div>
        <div className="form-control">
          <label></label>
          <button type="submit">Login</button>
        </div>
      </form>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

useForm在上面的代码中,我们通过向每个函数传递一个唯一的名称,为每个从钩子函数获取的输入字段添加了一个注册函数,register如下所示:

{...register("email")}
Enter fullscreen mode Exit fullscreen mode

我们使用展开运算符,因此会将所有必需的事件处理程序(如)以及该输入字段的其他属性react-hook-form展开。onChangeonBlur

如果在组件内部添加一个元素console.log({ ...register("email") });,您将看到它返回的内容,如下所示:

日志

我们还添加了onSubmit传递给handleSubmit方法的函数,如下所示:

<form onSubmit={handleSubmit(onSubmit)}>
...
Enter fullscreen mode Exit fullscreen mode

请注意,您需要register为每个输入字段添加一个唯一的函数名称,以便react-hook-form跟踪数据的变化。

当我们提交表单时,该handleSubmit函数将处理表单提交。它会将用户输入的数据发送到另一个onSubmit函数,该函数会将用户数据记录到控制台。

const onSubmit = (data) => {  
 console.log(data);
};
Enter fullscreen mode Exit fullscreen mode

现在,运行npm start`or`yarn start命令启动应用程序,您将看到以下屏幕:

登录日志

这是一个代码沙盒演示

如您所见,当我们提交表单时,用户输入的详细信息会显示在控制台中。

此外,与没有使用该功能的代码react-hook-form(我们在本文开头的代码沙盒演示中看到了该代码)相比,这段代码要简单得多。

这是因为我们不需要为每个输入字段添加valueandonChange处理程序,也不需要自己管理应用程序状态。

如何为表单添加验证

现在,让我们为输入字段添加必填字段和最小长度验证。

为了添加验证功能,我们可以register像这样将一个对象作为第二个参数传递给函数:

<input
  type="text"
  name="email"
  {...register("email", {
    required: true
  })}
/>

<input
  type="password"
  name="password"
  {...register("password", {
    required: true,
    minLength: 6
  })}
/>
Enter fullscreen mode Exit fullscreen mode

这里,对于电子邮件字段,我们指定了必填字段验证。对于密码字段,我们指定了必填字段和最小6个字符长度验证。

当验证失败时,errors来自useForm钩子的对象将填充验证失败的字段。

因此,我们将使用该errors对象来显示自定义错误消息。

打开App.js文件,并将其内容替换为以下内容:

import React from "react";
import { useForm } from "react-hook-form";
import "./styles.css";

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

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

  return (
    <div className="App">
      <form onSubmit={handleSubmit(onSubmit)}>
        <div className="form-control">
          <label>Email</label>
          <input
            type="text"
            name="email"
            {...register("email", {
              required: true,
              pattern: /^[^@ ]+@[^@ ]+\.[^@ .]{2,}$/
            })}
          />
          {errors.email && errors.email.type === "required" && (
            <p className="errorMsg">Email is required.</p>
          )}
          {errors.email && errors.email.type === "pattern" && (
            <p className="errorMsg">Email is not valid.</p>
          )}
        </div>
        <div className="form-control">
          <label>Password</label>
          <input
            type="password"
            name="password"
            {...register("password", {
              required: true,
              minLength: 6
            })}
          />
          {errors.password && errors.password.type === "required" && (
            <p className="errorMsg">Password is required.</p>
          )}
          {errors.password && errors.password.type === "minLength" && (
            <p className="errorMsg">
              Password should be at-least 6 characters.
            </p>
          )}
        </div>
        <div className="form-control">
          <label></label>
          <button type="submit">Login</button>
        </div>
      </form>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

现在查看该应用程序,您将看到以下屏幕:

基本验证

这是一个代码沙盒演示

如您所见,提交表单后,当我们尝试在输入字段中输入值时,每个输入字段都会立即出现验证错误。

如果任何输入字段出现错误,该errors对象将填充我们用于显示自定义错误消息的错误类型,如下所示:

{errors.email && errors.email.type === "required" && (
    <p className="errorMsg">Email is required.</p>
)}
{errors.email && errors.email.type === "pattern" && (
    <p className="errorMsg">Email is not valid.</p>
)}
Enter fullscreen mode Exit fullscreen mode

这里,根据错误类型,我们会显示不同的错误信息。

使用ES11 可选链式运算符,您可以进一步简化上述代码,如下所示:

{errors.email?.type === "required" && (
    <p className="errorMsg">Email is required.</p>
)}
{errors.email?.type === "pattern" && (
    <p className="errorMsg">Email is not valid.</p>
)}
Enter fullscreen mode Exit fullscreen mode

同样地,我们也添加了密码字段验证功能。

另外,正如您所看到的,如果某个输入字段存在验证错误,则在提交表单时,该输入字段会自动获得焦点。

此外,只要存在验证错误,表单就不会提交。如果您查看浏览器控制台,就会发现console.log只有在表单有效且没有错误的情况下才会打印该声明。

因此,使用这种方法react-hook-form减少了我们需要编写的代码量。此外,验证功能也具有响应式设计,一旦字段有效,错误消息就会立即消失。

但是,随着每个字段的验证次数增加,条件检查和错误信息代码也会随之增加。因此,我们可以进一步重构代码,使其更加简洁。

请查看以下代码:

import React from "react";
import { useForm } from "react-hook-form";
import "./styles.css";

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

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

  return (
    <div className="App">
      <form onSubmit={handleSubmit(onSubmit)}>
        <div className="form-control">
          <label>Email</label>
          <input
            type="text"
            name="email"
            {...register("email", {
              required: "Email is required.",
              pattern: {
                value: /^[^@ ]+@[^@ ]+\.[^@ .]{2,}$/,
                message: "Email is not valid."
              }
            })}
          />
          {errors.email && <p className="errorMsg">{errors.email.message}</p>}
        </div>
        <div className="form-control">
          <label>Password</label>
          <input
            type="password"
            name="password"
            {...register("password", {
              required: "Password is required.",
              minLength: {
                value: 6,
                message: "Password should be at-least 6 characters."
              }
            })}
          />
          {errors.password && (
            <p className="errorMsg">{errors.password.message}</p>
          )}
        </div>
        <div className="form-control">
          <label></label>
          <button type="submit">Login</button>
        </div>
      </form>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

在上面的代码中,我们更改了电子邮件和密码验证代码。

对于电子邮件输入字段,我们修改了之前的代码:

 {...register("email", {
     required: true,
     pattern: /^[^@ ]+@[^@ ]+\.[^@ .]{2,}$/
 })}
Enter fullscreen mode Exit fullscreen mode

修改以下代码:

{...register("email", {
    required: "Email is required.",
    pattern: {
        value: /^[^@ ]+@[^@ ]+\.[^@ .]{2,}$/,
        message: "Email is not valid."
    }
})}
Enter fullscreen mode Exit fullscreen mode

在这里,我们在添加验证功能的同时,直接提供了我们想要显示的错误消息。

因此,我们不再需要为每个验证添加额外的检查。我们使用对象message内部提供的属性errors来显示每个输入字段的错误信息,如下所示:

{errors.email && <p className="errorMsg">{errors.email.message}</p>}
Enter fullscreen mode Exit fullscreen mode

这样一来,代码就得到了进一步简化,便于将来添加额外的验证。

请注意,如果存在验证错误,则不会执行 onSubmit 处理程序,并且相应的输入字段将自动获得焦点(这是一件好事)。

这是更新后的代码沙盒演示

如何添加多个验证

您甚至可以通过添加对象为输入字段提供多重验证validate。如果您需要执行类似这样的复杂验证,这将非常有用:

<input
    type="password"
    name="password"
    {...register("password", {
        required: true,
        validate: {
            checkLength: (value) => value.length >= 6,
            matchPattern: (value) =>
            /(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?!.*\s)(?=.*[!@#$*])/.test(
                value
            )
        }
    })}
/>
Enter fullscreen mode Exit fullscreen mode

要显示错误信息,我们这样使用它:

{errors.password?.type === "required" && (
    <p className="errorMsg">Password is required.</p>
)}
{errors.password?.type === "checkLength" && (
    <p className="errorMsg">
        Password should be at-least 6 characters.
    </p>
)}
{errors.password?.type === "matchPattern" && (
    <p className="errorMsg">
        Password should contain at least one uppercase letter, lowercase
letter, digit, and special symbol.
    </p>
)}
Enter fullscreen mode Exit fullscreen mode

这是一个代码沙盒演示

多重验证

如何重置表单值

有时,在执行某些操作后,我们需要重置/清除用户输入的数据。

例如,表单提交后,我们希望显示成功消息,然后清除表单数据,这样用户就不会重新提交相同的数据。

在这种情况下,我们可以调用reset钩子返回的函数useForm来清除表单数据。

const { reset } = useForm();
Enter fullscreen mode Exit fullscreen mode

这是一个代码沙盒演示

重置值

reset函数还接受一个可选对象,您可以在其中传递要重置表单数据的值:

reset({
    username: "Alex",
    email: "alex@example.com",
    password: "Test@123"
});
Enter fullscreen mode Exit fullscreen mode

username这里,email应该password与传递给函数的名称匹配register,以便相应的输入字段将被设置为传递的值。

如何使用默认值设置表单初始值

useForm钩子接受一个选项列表,其中一个选项是defaultValues

我们可以这样defaultValues为表单元素设置初始值,并在页面切换时重新设置它们:

const { user } = props;
const {
    register,
    handleSubmit,
    formState: { errors }
} = useForm({
   defaultValues: {
      first_name: user.first_name,
      last_name: user.last_name
    }
});

// JSX

<Form.Control
    type="text"
    {...register("first_name")}
/>

<Form.Control
    type="text"
    {...register("last_name")}
/>
Enter fullscreen mode Exit fullscreen mode

在上面的代码中,register我们为函数传递了first_name名称。这意味着defaultValues我们在设置初始值时使用了相同的名称。

因此,要正确设置输入值,您需要使用register与设置初始值函数中相同的名称defaultValues

这是一个代码沙盒演示

默认值演示

如何将 react-hook-form 与其他库一起使用

有时,我们可能会使用一些外部库,例如react-select,以允许在下拉菜单中进行多项选择。

在这种情况下,我们无法直接添加register显示下拉选择框的功能。因此,如果我们想react-hook-form在不编写自定义代码和处理函数的情况下添加验证,可以使用Controller组件,react-hook-form如下所示:

import React from "react";
import { useForm, Controller } from "react-hook-form";
import Select from "react-select";
import "./styles.css";

const departments = [
  { value: "Computer-Science", label: "Computer Science" },
  { value: "Physics", label: "Physics" },
  { value: "Chemistry", label: "Chemistry" },
  { value: "Mathematics", label: "Mathematics" }
];

export default function App() {
  const {
    control,
    handleSubmit,
    formState: { errors }
  } = useForm();

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

  return (
    <div className="App">
      <form onSubmit={handleSubmit(onSubmit)}>
        <div className="form-control">
          <label>Select Department of Interest</label>
          <Controller
            name="department"
            control={control}
            rules={{ required: true }}
            render={({ field }) => (
              <Select {...field} isMulti options={departments} />
            )}
          />
          {errors.department && (
            <p className="errorMsg">This is a required field.</p>
          )}
        </div>
        <div className="form-control">
          <label></label>
          <button type="submit">Submit</button>
        </div>
      </form>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

这是一个代码沙盒演示

如上面的代码所示,我们Controller在顶部导入了组件:

import { useForm, Controller } from "react-hook-form";
Enter fullscreen mode Exit fullscreen mode

以及controluseForm这样的钩子:

const {
    control,
    handleSubmit,
    formState: { errors }
} = useForm();
Enter fullscreen mode Exit fullscreen mode

注意,我们register这里并没有使用该函数。

使用该react-select库实现多选功能的常规方法如下:

import Select from "react-select";

// use
<Select isMulti options={options} />
Enter fullscreen mode Exit fullscreen mode

但是要使用它,react-hook-form我们需要将其包装在Controller组件中:

<Controller
    name="department"
    control={control}
    rules={{ required: true }}
    render={({ field }) => (
       <Select {...field} isMulti options={options} />
    )}
 />
Enter fullscreen mode Exit fullscreen mode

这里,我们必须为nameprop提供一个唯一的值Controller

验证规则作为 prop 的一部分添加rules,我们使用该renderprop 来渲染Select下拉菜单。

控制器组件

如何在 react-hook-form 中使用其他输入类型

在本节中,我们将学习如何使用单选按钮和复选框react-hook-form

请查看以下代码:

import React from "react";
import { Button, Form } from "react-bootstrap";
import { useForm } from "react-hook-form";
import "./styles.css";

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

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

  return (
    <div className="container">
      <form onSubmit={handleSubmit(onSubmit)}>
        <Form.Group className="mb-3" controlId="email">
          <Form.Label>Email</Form.Label>
          <Form.Control
            type="email"
            placeholder="Enter your email"
            {...register("email", {
              required: "Please enter your email",
              pattern: {
                value: /^[^@ ]+@[^@ ]+\.[^@ .]{2,}$/,
                message: "Please enter a valid email"
              }
            })}
          />
          {errors.email && <p className="errorMsg">{errors.email.message}</p>}
        </Form.Group>
        <Form.Group className="mb-3" controlId="gender">
          <Form.Label>Select Gender</Form.Label>
          <Form.Check
            type="radio"
            label="Male"
            value="male"
            {...register("gender", {
              required: "Please select your gender"
            })}
          />
          <Form.Check
            type="radio"
            label="Female"
            value="female"
            {...register("gender")}
          />
          {errors.gender && <p className="errorMsg">{errors.gender.message}</p>}
        </Form.Group>
        <Form.Group className="mb-3" controlId="skills">
          <Form.Label>Select Your Skills</Form.Label>
          <Form.Check
            type="checkbox"
            label="JavaScript"
            value="JavaScript"
            {...register("skills", {
              required: "Please select at-least one skill"
            })}
          />
          <Form.Check
            type="checkbox"
            label="React"
            value="react"
            {...register("skills")}
          />
          <Form.Check
            type="checkbox"
            label="Node.js"
            value="nodejs"
            {...register("skills")}
          />
          <Form.Check
            type="checkbox"
            label="Angular"
            value="angular"
            {...register("skills")}
          />
          {errors.skills && <p className="errorMsg">{errors.skills.message}</p>}
        </Form.Group>
        <label></label>
        <Button type="submit" variant="primary">
          Submit
        </Button>
      </form>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

这是一个代码沙盒演示

在上面的代码中,我使用了react-bootstrap来使 UI 看起来更好,所以它Form.Check是一个react-bootstrap组件。

你需要记住的关键一点是,我们没有给register一组单选按钮和复选框使用相同的功能名称,例如:

<Form.Check
    type="radio"
    label="Male"
    value="male"
    {...register("gender", {
        required: "Please select your gender"
    })}
/>
<Form.Check
    type="radio"
    label="Female"
    value="female"
    {...register("gender")}
/>
Enter fullscreen mode Exit fullscreen mode

在上面的代码中,我们将gender单选按钮命名为“”,并将skills所有复选框命名为“”,如下所示:

<Form.Check
    type="checkbox"
    label="JavaScript"
    value="JavaScript"
    {...register("skills", {
        required: "Please select at-least one skill"
    })}
/>
<Form.Check
    type="checkbox"
    label="React"
    value="react"
    {...register("skills")}
/>
<Form.Check
    type="checkbox"
    label="Node.js"
    value="nodejs"
    {...register("skills")}
/>
<Form.Check
    type="checkbox"
    label="Angular"
    value="angular"
    {...register("skills")}
/>
Enter fullscreen mode Exit fullscreen mode

另外,请注意,必填字段验证仅针对第一个单选按钮或复选框添加。由于我们使用了相同的名称,因此无需为每个单选按钮或复选框添加相同的验证。

单选按钮 复选框

如何设置单选按钮和复选框的初始值

有时我们可能需要在页面加载时显示预先选择的单选按钮或复选框,在这种情况下,我们可以再次使用defaultValues钩子的选项useForm

请查看以下代码:

import React from "react";
import { Button, Form } from "react-bootstrap";
import { useForm } from "react-hook-form";
import "./styles.css";

const initialValues = {
  gender: "male",
  skills: {
    JavaScript: true,
    react: false,
    nodejs: true,
    angular: false
  }
};

export default function App() {
  const {
    register,
    handleSubmit,
    formState: { errors }
  } = useForm({
    defaultValues: {
      gender: initialValues.gender,
      skills: Object.keys(initialValues.skills).filter(
        (item) => initialValues.skills[item] === true
      )
    }
  });

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

  return (
    <div className="container">
      <form onSubmit={handleSubmit(onSubmit)}>
        <Form.Group className="mb-3" controlId="email">
          <Form.Label>Email</Form.Label>
          <Form.Control
            type="email"
            placeholder="Enter your email"
            {...register("email", {
              required: "Please enter your email",
              pattern: {
                value: /^[^@ ]+@[^@ ]+\.[^@ .]{2,}$/,
                message: "Please enter a valid email"
              }
            })}
          />
          {errors.email && <p className="errorMsg">{errors.email.message}</p>}
        </Form.Group>
        <Form.Group className="mb-3" controlId="gender">
          <Form.Label>Select Gender</Form.Label>
          <Form.Check
            type="radio"
            label="Male"
            value="male"
            {...register("gender", {
              required: "Please select your gender"
            })}
          />
          <Form.Check
            type="radio"
            label="Female"
            value="female"
            {...register("gender")}
          />
          {errors.gender && <p className="errorMsg">{errors.gender.message}</p>}
        </Form.Group>
        <Form.Group className="mb-3" controlId="skills">
          <Form.Label>Select Your Skills</Form.Label>
          <Form.Check
            type="checkbox"
            label="JavaScript"
            value="JavaScript"
            {...register("skills", {
              required: "Please select at-least one skill"
            })}
          />
          <Form.Check
            type="checkbox"
            label="React"
            value="react"
            {...register("skills")}
          />
          <Form.Check
            type="checkbox"
            label="Node.js"
            value="nodejs"
            {...register("skills")}
          />
          <Form.Check
            type="checkbox"
            label="Angular"
            value="angular"
            {...register("skills")}
          />
          {errors.skills && <p className="errorMsg">{errors.skills.message}</p>}
        </Form.Group>
        <label></label>
        <Button type="submit" variant="primary">
          Submit
        </Button>
      </form>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

这是一个代码沙盒演示

上面的代码中,我们有一个initialValues对象,其中包含我们希望在页面初始加载时设置的值:

const initialValues = {
  gender: "male",
  skills: {
    JavaScript: true,
    react: false,
    nodejs: true,
    angular: false
  }
};
Enter fullscreen mode Exit fullscreen mode

由于我们可以拥有多种技能,因此技能skills是一个对象,如上所示。所以,我们希望显示选中的单选按钮(如果其值为“男性”),并且我们只想显示选中的、其值true在对象中的复选框skills

因此,对于该选项,我们使用该方法defaultValues遍历对象,以找出如下所示的选项:skillsfilterskillstrue

const {
    register,
    handleSubmit,
    formState: { errors }
  } = useForm({
    defaultValues: {
      gender: initialValues.gender,
      skills: Object.keys(initialValues.skills).filter(
        (item) => initialValues.skills[item] === true
      )
    }
  });
Enter fullscreen mode Exit fullscreen mode

由于 ` JavaScriptand` 的nodejs值是 `is` true,因此方法skills后的数组filter将变为`is` ["JavaScript", "nodejs"],所以defaultValues对象将如下所示:

useForm({
    defaultValues: {
        gender: 'male',
        skills: ["JavaScript", "nodejs"]
    }
});
Enter fullscreen mode Exit fullscreen mode

因此,当页面加载时,默认情况下只会选择/勾选male性别和JavaScript技能。Node.js

请注意,对象中使用的大小写必须与复选框指定的skills大小写一致。value

所以即使复选框的标签是Node.js,它的值也是,nodejs所以我们使用nodejs作为对象中的键initialValues

下面展示的是页面加载时的效果演示。

默认部分

就这样!你已经学会了如何使用 react-hook-form 在 React 中更轻松地构建复杂的表单。

感谢阅读!

如果你想从零开始详细学习 Redux,并构建 3 个应用程序以及完整的食品订购应用程序,请查看我的Redux 精通课程。

在本课程中,您将学习到:

  • Redux 基础与进阶
  • 如何管理数组和对象的复杂状态
  • 如何使用多个 reducer 来管理复杂的 Redux 状态
  • 如何调试 Redux 应用
  • 如何在 React 中使用 Redux,并使用 react-redux 库使你的应用程序具有响应式特性。
  • 如何使用 redux-thunk 库处理异步 API 调用
  • 使用 Redux 构建 3 个不同的应用程序

还有更多。

最后,我们将从零开始构建一个完整的食品订购应用程序,集成 Stripe 以接受付款,并将其部署到生产环境中。

想及时获取有关 JavaScript、React 和 Node.js 的最新内容吗?请在 LinkedIn 上关注我

文章来源:https://dev.to/myogeshchavan97/best-library-to-create-simple-and-complex-forms-in-react-k73