React-hook-form:递归地将道具注入嵌套的自定义字段
React-hook-form: recursively inject props to nested custom fields
我想使用 react-hook-form 设置自定义 Form
组件,该组件可以处理可能嵌套或包装在其他元素中的字段。我的方法是遍历组件树并递归地将 register
和 errors
(由 useForm() 返回)传递给作为输入字段的所有叶节点。
例如,一个简单的注册表单。名字和姓氏字段包含在 div 中,将它们设置为在同一行。表格如下所示:
<Form
onSubmit={onSubmit}
styles={["login_form"]}
showButton
buttonText='SIGN UP'>
// These are the wrapped fields
<div className='signup_name_field'>
<TextInput name={"fname"} label={"first"} />
<TextInput name={"lname"} label={"last"} />
</div>
<TextInput name={"email"} label={"email"} />
<TextInput password={true} name={"password"} label={"password"} />
<TextInput
password={true}
name={"passwordConfirm"}
label={"confirm password"}
/>
</Form>
我按照 react-hook-form 的示例创建了一个自定义表单组件,但添加了一个递归函数来处理嵌套或包装的字段:
const recursiveInjectProps: any = (children: any) => {
return React.Children.map(children, (child) => {
if (child.props.children) {
recursiveInjectProps(child.props.children);
return child;
} else {
if (child.props.name) {
return React.createElement(child.type, {
...{
...child.props,
register: register,
key: child.props.name,
},
});
} else {
return child;
}
}
});
};
return (
<form className={styles.join(" ")} onSubmit={handleSubmit(onSubmit)}>
{recursiveInjectProps(children)}
{renderButton()}
</form>
);
TextInput 看起来像这样:
const checkRegister = () => {
if (register) {
return (
<div className='login_field'>
<input
className='login_input'
name={name}
placeholder={label}
ref={register(validation)}
type={password ? "password" : "text"}
{...rest}
/>
<label htmlFor={name} className='login_label' />
{errors && errors[name] && errors[name].message}
</div>
);
} else {
return <div>no dice</div>;
}
};
return checkRegister();
问题是 recursiveInjectProps()
无法为超过一层深的子级注入 register
和 errors
(因此,包裹在 div).
我知道这一点,因为当它呈现时,我在名称字段应该出现的地方看到“没有骰子”。
非常感谢对此的任何帮助。
也许你应该使用上下文 API: https://react-hook-form.com/api#useFormContext
import React from "react";
import { useForm, FormProvider, useFormContext } from "react-hook-form";
export default function App() {
const methods = useForm();
const onSubmit = data => console.log(data);
return (
<FormProvider {...methods} > // pass all methods into the context
<form onSubmit={methods.handleSubmit(onSubmit)}>
<NestedInput />
<input type="submit" />
</form>
</FormProvider>
);
}
function NestedInput() {
const { register } = useFormContext(); // retrieve all hook methods
return <input name="test" ref={register} />;
}
我想使用 react-hook-form 设置自定义 Form
组件,该组件可以处理可能嵌套或包装在其他元素中的字段。我的方法是遍历组件树并递归地将 register
和 errors
(由 useForm() 返回)传递给作为输入字段的所有叶节点。
例如,一个简单的注册表单。名字和姓氏字段包含在 div 中,将它们设置为在同一行。表格如下所示:
<Form
onSubmit={onSubmit}
styles={["login_form"]}
showButton
buttonText='SIGN UP'>
// These are the wrapped fields
<div className='signup_name_field'>
<TextInput name={"fname"} label={"first"} />
<TextInput name={"lname"} label={"last"} />
</div>
<TextInput name={"email"} label={"email"} />
<TextInput password={true} name={"password"} label={"password"} />
<TextInput
password={true}
name={"passwordConfirm"}
label={"confirm password"}
/>
</Form>
我按照 react-hook-form 的示例创建了一个自定义表单组件,但添加了一个递归函数来处理嵌套或包装的字段:
const recursiveInjectProps: any = (children: any) => {
return React.Children.map(children, (child) => {
if (child.props.children) {
recursiveInjectProps(child.props.children);
return child;
} else {
if (child.props.name) {
return React.createElement(child.type, {
...{
...child.props,
register: register,
key: child.props.name,
},
});
} else {
return child;
}
}
});
};
return (
<form className={styles.join(" ")} onSubmit={handleSubmit(onSubmit)}>
{recursiveInjectProps(children)}
{renderButton()}
</form>
);
TextInput 看起来像这样:
const checkRegister = () => {
if (register) {
return (
<div className='login_field'>
<input
className='login_input'
name={name}
placeholder={label}
ref={register(validation)}
type={password ? "password" : "text"}
{...rest}
/>
<label htmlFor={name} className='login_label' />
{errors && errors[name] && errors[name].message}
</div>
);
} else {
return <div>no dice</div>;
}
};
return checkRegister();
问题是 recursiveInjectProps()
无法为超过一层深的子级注入 register
和 errors
(因此,包裹在 div).
我知道这一点,因为当它呈现时,我在名称字段应该出现的地方看到“没有骰子”。
非常感谢对此的任何帮助。
也许你应该使用上下文 API: https://react-hook-form.com/api#useFormContext
import React from "react";
import { useForm, FormProvider, useFormContext } from "react-hook-form";
export default function App() {
const methods = useForm();
const onSubmit = data => console.log(data);
return (
<FormProvider {...methods} > // pass all methods into the context
<form onSubmit={methods.handleSubmit(onSubmit)}>
<NestedInput />
<input type="submit" />
</form>
</FormProvider>
);
}
function NestedInput() {
const { register } = useFormContext(); // retrieve all hook methods
return <input name="test" ref={register} />;
}