我正在使用 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;
查看高级用法的文档,看起来您需要直接在低级组件上调用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
已经创建该道具