如何在react中验证多步表单

IT技术 javascript reactjs react-hooks react-hook-form
2021-05-20 11:49:08

我有一个多步骤表单,我正在使用 react 制作它来处理我正在使用的验证react-hook-form

我已经完成了 90% 的事情,只有我面临的问题是获取动态的第二个表单数据。

我正在做的是

  • 在我的第一个表格中,当填写(验证)时,我有两个字段,我将转到下一个表格
  • 在我的下一个表单中,我有两个输入字段,在添加按钮上,用户也可以添加多行字段,这些工作正常

问题

  • 现在,当我在第二种形式中创建新字段时,我想验证它们,但不知道我该怎么做。

我做了什么

在我的主要组件中,我这样做是为了验证

const forms = [
  {
    fields: ['desig', 'dept'],
    component: () => (
      <Pro register={register} errors={errors} defaultValues={defaultValues} />
    ),
  },
  {
    fields: [
      `userInfo[0].fname`, // here I am facing issue if I am statically putting 0,1 then it is validating that perticular form
      `userInfo[0].sirname`,
    ],
    component: () => (
      <Basic
        register={register}
        errors={errors}
        defaultValues={defaultValues}
        inputHolder={inputHolder}
        deleteRow={deleteRow}
        addRow={addRow}
      />
    ),
  },
];

单击提交,我正在执行此操作

const handleSubmit = (e) => {
  triggerValidation(forms[currentForm].fields).then((valid) => {
    if (valid) {
      console.log('whole form data - ', JSON.stringify(defaultValues));
    }
  });
};

如果在form2中添加了两个数据,我想要如下数据

    {
  "fname": "dsteve",
  "sname": "smith",
  "userInfo": [
    {
      "desig": "ddd",
      "dept": "deptee"
    },
    {
      "desig": "ddd",
      "dept": "deptee"
    }
  ]
}

我已经做了一切,但只有我被卡住了,我知道问题出在哪里

而不是这个

fields: ["fname", "sname"],

我必须这样做

fields:[`userInfo[0].name, `userInfo[0].sname],

这个 0-1 我必须根据索引动态,我不知道我错过了什么

我尝试通过索引映射字段,inputHolder但没有用

编辑/更新

如果我这样做

fields:[`userInfo[0].name`,`userInfo[1].name`, `userInfo[0].sname`,`userInfo[1].sname],

所以它正在对两个字段进行验证,但这是我手动进行的,如果用户创建更多字段,那么应该动态获取这些字段。

这是我的代码沙箱,其中包含完整代码

这是我的代码沙箱

我愿意使用任何新方法,但应该使用react-hook-form并完全填充我正在尝试做的事情

我现在不知道如何推进我的方法

2个回答

您可以创建一个包含 2 个空字符串的数组,其中第一个表示第一行 F 名称,第二个表示 MainComponent 中 inputHolder 下的第一行 S 名称:

 const [inputHolder, setinputHolder] = useState([
    {
      id: 1,
      fname: "",
      sname: ""
    }
  ]);
  const [names, setNames] = useState(["", ""]);

接下来,每次用户添加新行时,您都会将其添加到名称数组中的空字符串中。

 const addRow = () => {
    console.log(inputHolder.length);
    let item = {
      id: inputHolder.length + 1,
      fname: "",
      sname: ""
    };
    setinputHolder([...inputHolder, item]);
    setNames([...names, "", ""]);
   
  };

其中每个空字符串代表 F 名称和 S 名称。最后,fields 以第二种形式设置为名称:

fields: names,
      component: (register, errors, defaultValues) => (
        <Form2
          register={register}
          errors={errors}
          defaultValues={defaultValues}
          inputHolder={inputHolder}
          addRow={addRow}
        />

我建议您使用yup作为验证工具。它是一个强大的工具。

  1. 为两种形式创建两个方案:
 import * as yup rom 'yup';
    
 const schema = yup.object().shape({
   field1: yup.string().required() // number, array - whatever,
   field2: yup.string().required(),
 })

也应该为第二种形式创建类似的模式

  1. 创建第一个表单并通过解析器应用验证器
import { yupResolver } from '@hookform/resolvers/yup';

const { register, handleSubmit } = useForm({
  resolver: yupResolver(schema),
});
  1. 对您的第二个表单执行相同的操作 - useForm + 验证解析器

  2. 下一部分是让你的第二个形式是动态的,所以一定要使用钩子useFieldArray

const { fields, append, remove } = useFieldArray({
  name: 'userInfo', *// key, a part of path to access your fields - userInfo[n].fname*
  control: form.control, *// to connect you fields to basic form* 
});
  1. 现在您可以创建动作*(按钮/链接)* 并将它们传递给{append, remove}动作。

  2. {fields}应该由 .map 默认呈现。一旦您尝试使用(n)计算部分验证您的第二个表单- 您的架构将应用于每个部分。

还有另一种解决方案,您可以跳过第二种形式的部分(如果您的第二种模式可能很大,我更喜欢这种方式)。

您可以将useFieldArray字段连接到第一个表单,并且您的单个验证模式如下所示:

 import * as yup rom 'yup';
    
 const infoSchema = yup.object().schema({
   firstName: yup.string(),
   lastName: yup.string(),
 })

 *// enhance infoSchema to your expected logic.* 

 const schema = yup.object().shape({
   field1: yup.string().required() // number, array - whatever,
   field2: yup.string().required(),
   userInfo: yup.array().of(infoSchema),
 })