首页 > 解决方案 > React-hook-form:递归注入 props 到嵌套的自定义字段

问题描述

我想使用 react-hook-form 设置一个自定义Form组件,该组件可以处理可能嵌套或包装在其他元素中的字段。我的方法是遍历组件树并递归地将registererrors(由 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 中的名称字段)。我知道这一点,因为当它呈现时,我看到名称字段应该在哪里“没有骰子”。

非常感谢您对此的任何帮助。

标签: reactjsformsrecursionreact-hook-form

解决方案


也许您应该使用上下文 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} />;
}

推荐阅读