具有全局状态的嵌套表单

Nested forms with global state

我正在构建一个大型表单应用程序。 问题是表单由许多嵌套表单组成。第一阶段/表格对所有用户都是相似的。然后,根据用户的输入,将显示不同的表单。这意味着每个表单都有自己的本地状态,并且在提交每个表单时,全局状态都会被更新。

为了清楚起见,请参阅下面的一小部分全局状态:

const [state, setState] = useState({
    startForm {
      email: "",
      priority: "",
      requestType: "",
      dueDate: "",
    },
    designRequest: {
      designType: "",
      yellow: { client:"" , message: "" },
      red: { change: "", parameter: "" }
    }
  }
  );


const handleStartStepData = (startStepData) => { var startStep = {...state.startForm} state.startForm = startStepData setState({ startStep })
 };

return ( <StartForm state={startStepState} onChange={handleStartStepData}/>

)

开始表格:

export const StartForm = (props) => {
  
  const methods = useForm();

  const [state, setState] = useState({
    email: "",
    priority: "",
    requestType: "",
    dueDate: "",
   
  });


  const onSubmit = (data) => {
    const startFormState = data;
    props.onChange(startFormState);
  };

填写开始表单(电子邮件、优先级、请求类型和截止日期)后,屏幕上将显示不同的表单,具体取决于请求类型。因此,例如,如果用户选择了一个设计请求,他们将在黄色和红色请求之间进行选择。 我正在使用 React 表单挂钩以及 material UI 组件。我尝试为父级(全局表单)上的每个小表单设置一个句柄提交,但每个小表单都会覆盖全局状态而不是合并它。 我是 React 的新手,可以使用您的任何想法来更好地管理此应用程序中的状态。

正确的做法是使用 FormProvider 和 useFormContext。您所有的小表单都应嵌套在 FormProvider 中。

参见 codesandbox 上的示例 - https://codesandbox.io/s/react-hook-form-v7-form-context-forked-t02g0?file=/src/index.js:0-1602

文档 = https://react-hook-form.com/api/useformcontext

import React, { useState } from "react";
import ReactDOM from "react-dom";
import { useForm, FormProvider, useFormContext } from "react-hook-form";

import "./styles.css";

export default function App() {
  const methods = useForm();
  const [formData, setFormData] = useState();
  const onSubmit = (data) => setFormData(data);

  console.log(methods.formState.errors);

  return (
    <>
      <FormProvider {...methods}>
        {" "}
        {/* // pass all methods into the context */}
        <form onSubmit={methods.handleSubmit(onSubmit)}>
          <NestedNameEmailForm />
          <NestedAddressForm />
          <input type="submit" />
        </form>
      </FormProvider>
      <p>DATA</p>
      <pre style={{ color: "white" }}>{JSON.stringify(formData, null, 2)}</pre>
      <p>ERRORS</p>
      <pre style={{ color: "white" }}>
        {JSON.stringify(Object.keys(methods.formState.errors), null, 2)}
      </pre>
    </>
  );
}

function NestedNameEmailForm() {
  const { register } = useFormContext(); // retrieve all hook methods
  return (
    <>
      <input
        {...register("first", {
          required: true
        })}
        placeholder="First"
      />
      <input
        {...register("last", {
          required: true
        })}
        placeholder="Last"
      />
      <input
        {...register("email", {
          required: true
        })}
        placeholder="Email"
      />
    </>
  );
}

function NestedAddressForm() {
  const { register } = useFormContext(); // retrieve all hook methods
  return (
    <>
      <input
        {...register("address_line_1", {
          required: true
        })}
        placeholder="Address Line 1"
      />
      <input {...register("address_line_2")} placeholder="Address Line 1" />
      <input
        {...register("city", {
          required: true
        })}
        placeholder="City"
      />
      <input
        {...register("state", {
          required: true
        })}
        placeholder="State"
      />
      <input
        {...register("zip", {
          required: true
        })}
        placeholder="Zip"
      />
    </>
  );
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);