React Hook Form:提交带有嵌套组件的表单或提取嵌套组件的字段提交

Posted

技术标签:

【中文标题】React Hook Form:提交带有嵌套组件的表单或提取嵌套组件的字段提交【英文标题】:React Hook Form: Submit a form with nested components or extract fields of nested components to submit 【发布时间】:2021-03-22 09:23:33 【问题描述】:

我有一个包含多个输入字段或单选按钮的表单,其中包含多个组件(每个组件都是功能组件或基于类的组件)。当我提交表单时,我要么想提交嵌套在组件中的字段以及表单数据,要么我应该能够提取字段数据然后提交它们(不确定哪种方法最好,为什么?)。我怎样才能做到这一点?

代码:

import React from "react";
import  useForm  from "react-hook-form";

export default function TestComponent() 
  const  register, handleSubmit, errors  = useForm();
  const onSubmit = data => console.log(data);

  return (
    <form onSubmit=handleSubmit(onSubmit)>
      <label htmlFor="name">Name</label>
      <input type="text" id="name" name="name" ref=register( required: true, maxLength: 30 ) />
      errors.name && errors.name.type === "required" && <span>This is required</span>
      errors.name && errors.name.type === "maxLength" && <span>Max length exceeded</span> 
      <NestedComponent1 />
      <NestedComponent2 />
      <input type="submit" />
    </form>
  );


function NestedComponent1() 
    return (
        <div>
            <input type="text" id="nested-name" name="nestedName" />
            <input type="text" id="nested-name2" name="nestedName2" />
            <input type="text" id="nested-name3" name="nestedName3" />
        </div>
    );


function NestedComponent2() 
    return (
        <div>
            <input type="text" id="nested-comp2-name" name="nestedcomp2Name" />
            <input type="text" id="nested-comp2-name2" name="nestedcomp2Name2" />
            <input type="text" id="nested-comp2-name3 name="nestedcomp2Name3" />
        </div>
    );

【问题讨论】:

【参考方案1】:

您可以使用钩子useFormContext 来避免将上下文作为道具https://react-hook-form.com/api/useformcontext 传递

您只需用FormProvider 组件包装您的表单,这样您就可以在嵌套组件中使用useFormContext 获取上下文

export default function TestComponent() 
    const methods = useForm();
    const  register, handleSubmit, errors  = methods;
    const onSubmit = data => console.log(data);

    return (
    <FormProvider ...methods > // pass all methods into the context
        <form onSubmit=handleSubmit(onSubmit)>
        <label htmlFor="name">Name</label>
        <input type="text" id="name" name="name" ref=register( required: true, maxLength: 30 ) />
        errors.name && errors.name.type === "required" && <span>This is required</span>
        errors.name && errors.name.type === "maxLength" && <span>Max length exceeded</span> 
        <NestedComponent1 />
        <input type="submit" />
        </form>
    </FormProvider>
    );


function NestedComponent1() 
    const  register  = useFormContext(); // retrieve all hook methods
    
    return (
        <div>
            <input ...register("nestedName") type="text" id="nested-name" name="nestedName"  />
            <input ...register("nestedName2") type="text" id="nested-name2" name="nestedName2" />
            <input ...register("nestedName3") type="text" id="nested-name3" name="nestedName3" />
        </div>
    );


【讨论】:

【参考方案2】:

要从嵌套组件中提取数据,您可以在 TestComponent 中添加“useState”并将 onChange 函数传递给嵌套组件。

import React from "react";
import  useForm  from "react-hook-form";

export default function App() 
  const  register, handleSubmit, errors  = useForm();
  const onSubmit = (data) => console.log(data);

  return (
    <form onSubmit=handleSubmit(onSubmit)>
      <label htmlFor="name">A</label>
      <input
        type="text"
        id="name"
        name="name"
        ref=register( required: true, maxLength: 30 )
      />
      errors.name && errors.name.type === "required" && (
        <span>This is required</span>
      )
      errors.name && errors.name.type === "maxLength" && (
        <span>Max length exceeded</span>
      )
      <NestedComponent1 register=register />
      <NestedComponent2 register=register />
      <input type="submit" />
    </form>
  );


function NestedComponent1(register) 
  return (
    <div style= display: "flex", flexDirection: "column" >
      <label htmlFor="nestedName">B</label>
      <input type="text" id="nested-name" name="nestedName" ref=register />
      <label htmlFor="nesteNamename2">C</label>
      <input type="text" id="nested-name2" name="nestedName2" ref=register />
      <label htmlFor="nestedName3">D</label>
      <input type="text" id="nested-name3" name="nestedName3" ref=register />
    </div>
  );


function NestedComponent2( register ) 
  return (
    <div style= display: "flex", flexDirection: "column" >
      <label htmlFor="nestedcomp2Name">E</label>
      <input
        type="text"
        id="nested-comp2-name"
        name="nestedcomp2Name"
        ref=register
      />
      <label htmlFor="nestedcomp2Name2">F</label>
      <input
        type="text"
        id="nested-comp2-name2"
        name="nestedcomp2Name2"
        ref=register
      />
      <label htmlFor="nestedcomp2Name3">G</label>
      <input
        type="text"
        id="nested-comp2-name3"
        name="nestedcomp2Name3"
        ref=register
      />
    </div>
  );

【讨论】:

我们不能通过React-hook-form 做同样的事情吗?我的意思是我们没有办法只用它来收集所有嵌套字段数据吗?因为当我点击提交时,我希望 React Hook Form 读取字段数据 我更改了答案,请查看上方。您需要做的就是将注册方法发送给孩子。另请查看 react-hook-form 的官方文档:react-hook-form.com/advanced-usage react-hook-form.com/advanced-usage 这可能会有所帮助 这是唯一适合我的解决方案。

以上是关于React Hook Form:提交带有嵌套组件的表单或提取嵌套组件的字段提交的主要内容,如果未能解决你的问题,请参考以下文章

带有 Chakra UI 的 React-hook-form 未在 NextJS 中显示验证错误消息

react-hook-form yup 解析器,reactStrap 解决子组件错误的问题

如何使用带有 Typescript 的 React Hook 表单(输入组件)

使用带有 Material-UI 自动完成功能的 react-hook-form 控制器的正确方法

如何将 react-hook-form 用于嵌套数组

React JS 多个提交按钮 react-hook-form