React Hook Form 注册相同字段名的不同表单

React Hook Form Register Different Forms With Same Field Names

我有一个 material ui 步进器,其中有多种形式使用 react-hook-form。当我在步骤之间切换时,我希望有一个新的 useForm 挂钩来创建新的 register 函数来注册新的表单字段,但是当我在步骤之间切换时,第二个表单具有第一个表单的数据。我至少看到一个问题,有人试图在同一组件的同一页面上创建两个表单,但在这种情况下,我试图在不同的步骤中使用组件的不同实例创建两个独特的表单。似乎 react-hook-form 没有更新 useForm 挂钩,或者正在回收添加到第一个 register 调用的表单字段。

为什么 react-hook-form 不使用新的 register 函数将表单字段注册到新的 useForm 挂钩?或者至少,为什么不在步骤之间创建新的 useForm 挂钩?

DynamicForm 组件。这些组件中有两个(步进器中的每个步骤一个)。

import { Button, Grid } from "@material-ui/core";
import React from "react";
import { useForm } from "react-hook-form";
import { buttonStyles } from "../../../styles/buttonStyles";

import AppCard from "../../shared/AppCard";
import { componentsMap } from "../../shared/form";

export const DynamicForm = (props) => {
  const buttonClasses = buttonStyles();
  const { defaultValues = {} } = props;
  const { handleSubmit, register } = useForm({ defaultValues });

  const onSubmit = (userData) => {
    props.handleSubmit(userData);
  };

  return (
    <form
      id={props.formName}
      name={props.formName}
      onSubmit={handleSubmit((data) => onSubmit(data))}
    >
      <AppCard
        headline={props.headline}
        actionButton={
          props.actionButtonText && (
            <Button className={buttonClasses.outlined} type="submit">
              {props.actionButtonText}
            </Button>
          )
        }
      >
        <Grid container spacing={2}>
          {props.formFields.map((config) => {
            const FormComponent = componentsMap.get(config.component);
            return (
              <Grid key={`form-field-${config.config.name}`} item xs={12}>
                <FormComponent {...config.config} register={register} />
              </Grid>
            );
          })}
        </Grid>
      </AppCard>
    </form>
  );
};

N.B。图像是相同的,因为表单将包含相同的信息,即名称相同的表单字段。

第一种形式的条目:

第二种形式的条目:

每个表单都是使用这样的配置创建的:

{
  component: DynamicForm,
  label: "Stepper Label",
  config: {
    headline: "Form 1",
    actionButtonText: "Next",
    formName: 'form-name',
    defaultValues: defaultConfigObject,
    formFields: [
      {
        component: "AppTextInput",
        config: {
          label: "Field 1",
          name: "field_1",
        },
      },
      {
        component: "AppTextInput",
        config: {
          label: "Field2",
          name: "field_2",
        },
      },
      {
        component: "AppTextInput",
        config: {
          label: "Field3",
          name: "field_3",
        },
      },
      {
        component: "AppTextInput",
        config: {
          label: "Field4",
          name: "field4",
        },
      },
    ],
    handleSubmit: (formData) => console.log(formData),
  },
},

步骤中的活动组件处理如下:

import { Button, createStyles, makeStyles, Theme } from "@material-ui/core";
import React, { useContext, useEffect, useState } from "react";
import { StepperContext } from "./StepperProvider";

const useStyles = makeStyles((theme: Theme) =>
  createStyles({
    buttonsContainer: {
      margin: theme.spacing(2),
    },
    buttons: {
      display: "flex",
      justifyContent: "space-between",
    },
  })
);
export const StepPanel = (props) => {
  const { activeStep, steps, handleBack, handleNext, isFinalStep } = useContext(
    StepperContext
  );

  const [activeComponent, setActiveComponent] = useState(steps[activeStep]);

  const classes = useStyles();

  useEffect(() => {
    setActiveComponent(steps[activeStep]);
  }, [activeStep]);

  return (
    <div>
      <activeComponent.component {...activeComponent.config} />
      {
        isFinalStep ? (
          <div className={classes.buttonsContainer}>
            <div className={classes.buttons}>
              <Button disabled={activeStep === 0} onClick={handleBack}>
                Back
              </Button>
              <Button
                variant="contained"
                color="primary"
                onClick={props.finishFunction}
              >
                Finish And Submit
              </Button>
            </div>
          </div>
        ) 
        : 
        null
      }
    </div>
  );
};

从你的图片来看,每个表格看起来都一样。您应该尝试为您的组件提供一个唯一的 key 值,以便 React 知道每个表单都是不同的。在这种情况下,它可以是步骤编号,例如:

<activeComponent.component {...props} key='form-step-1'>