0

我有组件,在每个组件中,我都有一个表单,点击下一个我打开一个新表单(调用新组件),当它是最后一个时,我将其更改为提交。

我想要达到的目标

1:在每次下一步和返回单击时,我想使用 react-form-hook 验证我的表单

2:点击提交我应该能够看到所有的数据

3:点击后面的数据不应该从输入中丢失

问题

因此,对于验证,我使用react-hook-form,因为它使用起来非常简单,但是在这里我无法找到,因为我的按钮不在它们位于主要组件中的表单内,所以我将如何验证并提交表单提交点击所有数据。

我的代码

import React, { useState } from "react";
import Form1 from "./components/Form1";
import Form2 from "./components/Form2";
import Form3 from "./components/Form3";

function AddCompanyMain() {
  const [currState, setCurrState] = useState(1);
  const [allState, setAllstate] = useState(3);

  const moveToPrevious = () => {
    setCurrState(currState - 1);
  };
  const moveToNext = () => {
    setCurrState(currState + 1);
  };

  return (
    <div>
      <div class="progress">
        <div>{currState}</div>
      </div>

      {currState === 1 && <Form1 />}
      {currState === 2 && <Form2 />}
      {currState === 3 && <Form3 />}

      {currState !== 1 && (
        <button
          className="btn btn-primary"
          type="button"
          onClick={moveToPrevious}
        >
          back
        </button>
      )}
      {currState !== allState && (
        <button className="btn btn-primary" type="button" onClick={moveToNext}>
          next
        </button>
      )}

      {currState === 3 && (
        <button className="btn btn-primary" type="submit">
          Submit
        </button>
      )}
    </div>
  );
}

export default AddCompanyMain;

我的完整代码代码沙箱

我只是在寻找一种好的方法,因为这里我不能在每个组件中都提交,因为我必须在顶部显示步骤。

4

2 回答 2

1

您可以通过执行以下操作来解决您的问题:

  • 在 app.js 中,将表单存储在对象数组中,并根据步骤(currentFrom 状态)呈现它们。
  • 调用useForm父组件(不在子 Form 组件中)并将register, errors, defaultValues值作为道具传递给您的Form组件。
  • 在您的Form组件中,您需要register, etc作为道具抓取
  • 保持defaultValues状态并onClick在下一个/上一个中更新它们。您需要getValues然后使用setValues设置状态(defaultValues)

还:

  • 为了在下一个/上一个按钮单击时触发验证,您需要使用triggerValidation

  • 为了在单击下一个/上一个时保留值,您需要使用defaultValues道具

在这里查看工作演示

代码片段

import React, { useState } from "react";
import Form1 from "./components/Form1";
import Form2 from "./components/Form2";
import Form3 from "./components/Form3";
import { useForm } from "react-hook-form";

function AddCompanyMain() {
  const {
    register,
    triggerValidation,
    errors,
    setValue,
    getValues
  } = useForm();
  const [defaultValues, setDefaultValues] = useState({});

  const forms = [
    {
      fields: ["uname"],
      component: (register, errors, defaultValues) => (
        <Form1
          register={register}
          errors={errors}
          defaultValues={defaultValues}
        />
      )
    },
    {
      fields: ["lname"],
      component: (register, errors, defaultValues) => (
        <Form2
          register={register}
          errors={errors}
          defaultValues={defaultValues}
        />
      )
    },
    {
      fields: ["company"],
      component: (register, errors, defaultValues) => (
        <Form3
          register={register}
          errors={errors}
          defaultValues={defaultValues}
        />
      )
    }
  ];

  const [currentForm, setCurrentForm] = useState(0);

  const moveToPrevious = () => {
    setDefaultValues(prev => ({ ...prev, [currentForm]: getValues() }));

    triggerValidation(forms[currentForm].fields).then(valid => {
      if (valid) setCurrentForm(currentForm - 1);
    });
  };

  const moveToNext = () => {
    console.log(getValues());
    setDefaultValues(prev => ({ ...prev, [currentForm]: getValues() }));
    triggerValidation(forms[currentForm].fields).then(valid => {
      if (valid) setCurrentForm(currentForm + 1);
    });
  };

  const prevButton = currentForm !== 0;
  const nextButton = currentForm !== forms.length - 1;

  return (
    <div>
      <div class="progress">
        <div>{currentForm}</div>
      </div>

      {forms[currentForm].component(
        register,
        errors,
        defaultValues[currentForm]
      )}

      {prevButton && (
        <button
          className="btn btn-primary"
          type="button"
          onClick={moveToPrevious}
        >
          back
        </button>
      )}
      {nextButton && (
        <button className="btn btn-primary" type="button" onClick={moveToNext}>
          next
        </button>
      )}

      {currentForm === 3 && (
        <button className="btn btn-primary" type="submit">
          Submit
        </button>
      )}
    </div>
  );
}

export default AddCompanyMain;

注意 - 通常,在使用多步表单时,最好使用受控组件并维护父组件中的状态

于 2020-05-11T06:00:06.613 回答
1

您可以将每个组件的值状态提升到 parent,然后将 onChange 道具传递给每个组件以更新每个子组件的状态。我不确定这将如何与 react-hooks-form 一起使用,但这通常是您希望同步子组件状态的方式。

import React from "react";
import "./styles.css";

const FormOne = ({ value, onChange }) => (
  <div>
    Form 1
    <input type='text' value={value} onChange={e => onChange(e.target.value)} />
  </div>

)

const FormTwo = ({ value, onChange }) => (
  <div>
    Form 2
    <input type='text' value={value} onChange={e => onChange(e.target.value)} />
  </div>
)

const FormThree = ({ value, onChange }) => (
  <div>
    Form 3
    <input type='text' value={value} onChange={e => onChange(e.target.value)} />
  </div>
)

export default function App() {
  const [formOne, setFormOne] = React.useState('')
  const [formTwo, setFormTwo] = React.useState('')
  const [formThree, setFormThree] = React.useState('')
  const [index, setIndex] = React.useState(0)

  const moveUp = (e) => {
    e.preventDefault()

    if (index !== 2) {
      setIndex(index => index += 1)
    }
  }

  const moveDown = (e) => {
    e.preventDefault()

    if (index !== 0) {
      setIndex(index => index -= 1)
    }
  }

  const handleSubmit = (e) => {
    e.preventDefault()

    console.log(formOne, formTwo, formThree)
  }

  const form = index === 0
    ? <FormOne value={formOne} onChange={setFormOne} />
    : index === 1
    ? <FormTwo value={formTwo} onChange={setFormTwo} />
    : <FormThree value={formThree} onChange={setFormThree} />

  return (
    <div className="App">
      <form onSubmit={handleSubmit}>
        {form}
        {index !== 0 && <button onClick={moveDown}>Back</button>}
        {index !== 2
          ? <button onClick={moveUp}>Next</button>
          : <button type='submit'>Submit</button>
        }
      </form>
    </div>
  );
}
于 2020-05-07T05:40:06.267 回答