如何在自定义输入组件中处理 React Hook 表单验证?

问题描述 投票:0回答:1

我正在使用 React Hook Form 来处理我的 React 项目中的表单验证。虽然使用普通元素时一切正常,但当我尝试将输入包装在自定义组件中时,我遇到了问题。具体来说,诸如 minLength 和 maxLength 之类的验证未正确触发。它总是与所需的验证相悖。

这是我的设置示例: 父组件(Parent.jsx):

import { useForm } from "react-hook-form";
import Input from "./Components/Input.jsx";
import Button from "./Components/Button.jsx";

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

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

  return (
    <div className="App">
      <div className="container">
        <form onSubmit={handleSubmit(login)}>
          <Input
            type="text"
            name="username"
            {...register("username", {
              required: {
                value: true,
                message: "Username is required",
              },
              minLength: {
                value: 5,
                message: "Too Few Characters",
              },
               maxLength: {
                value: 15,
                message: "username length should not exceed 15",
              },
            })}
          />
          {errors.username && <p className="red">{errors.username.message}</p>}

          <Input
            type="password"
            name="password"
            {...register("password", {
              required: {
                value: true,
                message: "password is required",
              },
              minLength: {
                value: 6,
                message: "Password length should be greater than 6",
              },
              maxLength: {
                value: 15,
                message: "Password length should not exceed 15",
              },
            })}
          />
          {errors.password && <p className="error-red">{errors.password.message}</p>}

          <Button type="submit" />
        </form>
      </div>
    </div>
  );
}

自定义输入组件(Input.jsx):

import { forwardRef } from "react";
const Input = forwardRef(function Input(
  { type = "text", name = "", ...props },
  ref
) {
  return (
   <>
      <input
        placeholder=" "
        className="txt-input"
        type={type}
        ref={ref}
        {...props}
      />
      {name && (
        <label className="label-placeholder">
          {name.charAt(0).toUpperCase() + name.slice(1)}
        </label>
      )}
   </>
  );
});

export default Input;

  1. 使用forwardRef将React Hook Form中的ref转发到原生。
  2. 将所有属性(例如 onChange、onBlur)从父组件传递到自定义组件。
javascript reactjs react-hooks react-hook-form
1个回答
0
投票

查看高级用法的文档,看起来您需要直接在低级组件上调用register(例如

<input />

他们使用的示例代码(在“连接表单”标题下):

import { FormProvider, useForm, useFormContext } from "react-hook-form"

export const ConnectForm = ({ children }) => {
  const methods = useFormContext()

  return children({ ...methods })
}

export const DeepNest = () => (
  <ConnectForm>
    {({ register }) => <input {...register("deepNestedInput")} />}
  </ConnectForm>
)

export const App = () => {
  const methods = useForm()

  return (
    <FormProvider {...methods}>
      <form>
        <DeepNest />
      </form>
    </FormProvider>
  )
}

其中的关键部分是确保您使用创建的

Context
中的 register(可能来自
FormProvider
并可从
useFormContext
访问);这很可能是
useContext
createContext

的抽象版本

在您的示例中,这可能意味着代码将如下所示:

import { FormProvider, useForm, useFormContext } from "react-hook-form"

export const ConnectForm = ({ children }) => {
  const methods = useFormContext()

  return children({ ...methods })
}

export const CustomInput = ({ name, registerProps }) => (
  <ConnectForm>
    {({ register }) => <input name={name} {...register(name, registerProps)} />}
  </ConnectForm>
)

export const App = () => {
  const methods = useForm()

  return (
    <FormProvider {...methods}>
      <form>
        <CustomInput
          name={"username"}
          registerProps={{
            required: {
              value: true,
              message: "Username is required",
            },
            minLength: {
              value: 5,
              message: "Too Few Characters",
            },
             maxLength: {
              value: 15,
              message: "username length should not exceed 15",
            },
          }}
        />
      ...
      </form>
    </FormProvider>
  )
}

注意:您可能不需要在

name={name}
中传递
CustomInput
,因为我希望
register
已经创建该道具

© www.soinside.com 2019 - 2024. All rights reserved.