React Hook 表单注册具有相同字段名称的不同表单

时间:2021-03-27 11:50:05

标签: reactjs react-hook-form

我有一个材质 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>
  );
};

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

第一种形式的条目:

enter image description here

第二种形式的条目:

enter image description here

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

{
  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>
  );
};

1 个答案:

答案 0 :(得分:1)

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

  services.AddAuthentication(x=> {
            x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
            x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
        }).AddJwtBearer(x=> {
            x.RequireHttpsMetadata = false;
            x.SaveToken = true;
            x.TokenValidationParameters = new TokenValidationParameters()
            {
                ValidateIssuerSigningKey = true,
                IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(key)),
                ValidateIssuer = false,
                ValidateAudience = false,
                ValidateLifetime=true
            };
        });