Javascript 如何使用react以多步骤形式进行验证

Javascript 如何使用react以多步骤形式进行验证,javascript,reactjs,react-hooks,react-hook-form,Javascript,Reactjs,React Hooks,React Hook Form,我正在处理一个场景,在这个场景中,我必须完成一个我已经完成的多步骤表单,以及验证部分。我正在使用react hook表单进行验证 我有多步骤表格: 在第一种形式中,我有几个字段和一个单选按钮 默认情况下,自动生成通行证的单选按钮被勾选,因此在这种情况下,我无事可做 第二个是让我创建一个密码,因此在这种情况下,将显示一个输入字段,用户将创建密码 问题 在我的最终表格中,我正在进行如下验证: { fields: ["uname", "email", &

我正在处理一个场景,在这个场景中,我必须完成一个我已经完成的多步骤表单,以及验证部分。我正在使用
react hook表单
进行验证

我有多步骤表格:

  • 在第一种形式中,我有几个字段和一个单选按钮
  • 默认情况下,
    自动生成通行证的单选按钮被勾选,因此在这种情况下,我无事可做
  • 第二个是
    让我创建一个密码
    ,因此在这种情况下,将显示一个输入字段,用户将创建密码
问题

在我的最终表格中,我正在进行如下验证:

{
  fields: ["uname", "email", "password"], //to support multiple fields form
  component: (register, errors, defaultValues) => (
    <Form1
      register={register}
      errors={errors}
      defaultValues={defaultValues}
    />
  )
},
{
字段:[“uname”、“email”、“password”],//支持多字段表单
组件:(寄存器、错误、默认值)=>(
)
},
因此,为了验证uname、email和密码,我将传递上述值

但是,当单选按钮勾选自动生成密码时,它仍在处理验证,我单击next,它不会转到next for,因为password字段

如果我选中单选按钮作为
让我创建密码
,它将进入下一个表单,当我通过单击
返回
返回时,它将再次进入
自动生成的密码
,并且它不保持以前的状态。对于其他输入字段,它将处理以前的值,但单选按钮情况下不会处理


答案1原因是您的
字段:[“uname”、“email”、“password”]
是固定的,
密码总是要进行验证。
解决方案需要在应用程序中存储
表单1的状态
,以便您可以检查
自动生成密码
的状态是否处于从列表中删除密码状态

App.js

... other code
// need to move state and function form Form to app
const [show_input, setshow_input] = useState(false);

  const createInput = () => {
    setshow_input(true);
  };
  const auto_text = () => {
    setshow_input(false);
  };
  const forms = [
    {
      // validate based on show_input state
      fields: show_input ? ["uname", "email", "password"] : ["uname", "email"], //to support multiple fields form
      component: (register, errors, defaultValues) => (
        <Form1
          register={register}
          errors={errors}
          defaultValues={defaultValues}
          auto_text={auto_text}
          createInput={createInput}
          show_input={show_input}
        />
      )
    },
    {
      fields: ["lname"],
      component: (register, errors, defaultValues) => (
        <Form2
          register={register}
          errors={errors}
          defaultValues={defaultValues}
        />
      )
    },
    {
      component: (register, errors, defaultValues) => (
        <Form3
          register={register}
          errors={errors}
          defaultValues={defaultValues}
        />
      )
    }
  ];
... other code
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 MainComponent() {
  const {
    register,
    triggerValidation,
    defaultValues,
    errors,
    getValues
  } = useForm({
    // You can set default values here
    defaultValues: {
      uname: "Lol"
    }
  });
  console.log("Errors: ", errors);
  const [currentForm, setCurrentForm] = useState(0);

  // control password input visibility and Form1 fields
  const [passwordVisible, setPasswordVisible] = useState(false);

  const showPassword = () => {
    setPasswordVisible(true);
  };
  const hidePassword = () => {
    setPasswordVisible(false);
  };

  const forms = [
    {
      fields: passwordVisible
        ? ["uname", "email", "password"]
        : ["uname", "email"],
      component: (register, errors) => (
        <Form1
          // a key is needed to render a list
          key={0}
          // this will be used to set the css display property to block or none on each form
          shouldDisplay={currentForm === 0}
          register={register}
          errors={errors}
          showPassword={showPassword}
          hidePassword={hidePassword}
          passwordVisible={passwordVisible}
        />
      )
    },
    {
      fields: ["lname"],
      component: (register, errors) => (
        <Form2
          key={1}
          shouldDisplay={currentForm === 1}
          register={register}
          errors={errors}
        />
      )
    },
    {
      component: (register, errors) => (
        <Form3
          key={2}
          shouldDisplay={currentForm === 2}
          register={register}
          errors={errors}
          values={getValues()}
        />
      )
    }
  ];

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

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

  const prevButton = currentForm !== 0;
  const nextButton = currentForm !== forms.length - 1;
  const handleSubmit = e => {
    console.log("whole form data - ", getValues());
  };
  return (
    <div>
      <div className="progress">
        <div>{currentForm}</div>
      </div>

      {forms.map(form => form.component(register, errors))}

      {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 === 2 && (
        <button
          onClick={handleSubmit}
          className="btn btn-primary"
          type="submit"
        >
          Submit
        </button>
      )}
    </div>
  );
}

export default MainComponent;
。。。其他代码
//需要将状态和功能表单移动到应用程序
const[show_input,setshow_input]=useState(false);
常量createInput=()=>{
设置SHOW_输入(真);
};
常量自动_文本=()=>{
设置SHOW_输入(假);
};
常数形式=[
{
//基于show_输入状态进行验证
字段:显示输入?[“uname”、“email”、“password”]:[“uname”、“email”],//支持多字段表单
组件:(寄存器、错误、默认值)=>(
)
},
{
字段:[“lname”],
组件:(寄存器、错误、默认值)=>(
)
},
{
组件:(寄存器、错误、默认值)=>(
)
}
];
... 其他代码
回答2下一步时,将卸载
表单1
,因此其状态将被销毁。当您将Form1的状态存储在App.js中时,您也将修复此问题

好处:它更喜欢使用camalCase(例如:showInput)而不是下划线(show_input)


主要问题是有条件地呈现表单,以便删除所有以前的表单值。解决方案是保持所有窗体都已装入,只需根据选择的窗体使用
display:none
display:block
。这样,每当您转到下一个或上一个表单或提交表单时,所有值都将保持不变

第二个问题是,您在卸载密码字段时没有将其删除,因此当调用
moveToNext
时,
triggervalization
回调中的
valid
参数始终为false。我修复了这个问题,根据密码输入是否可见,有条件地设置Form1的字段

第三个问题是,您使用
defaultValues
的目的不正确。您可以使用
getValues()
获取当前表单值,它将返回表单的所有当前值

我为
uname
字段设置了默认值,只是作为一个示例,向您展示如何使用
defaultValues

您可以在此处查看完整的解决方案:

以下是所有更改的文件:

App.js

... other code
// need to move state and function form Form to app
const [show_input, setshow_input] = useState(false);

  const createInput = () => {
    setshow_input(true);
  };
  const auto_text = () => {
    setshow_input(false);
  };
  const forms = [
    {
      // validate based on show_input state
      fields: show_input ? ["uname", "email", "password"] : ["uname", "email"], //to support multiple fields form
      component: (register, errors, defaultValues) => (
        <Form1
          register={register}
          errors={errors}
          defaultValues={defaultValues}
          auto_text={auto_text}
          createInput={createInput}
          show_input={show_input}
        />
      )
    },
    {
      fields: ["lname"],
      component: (register, errors, defaultValues) => (
        <Form2
          register={register}
          errors={errors}
          defaultValues={defaultValues}
        />
      )
    },
    {
      component: (register, errors, defaultValues) => (
        <Form3
          register={register}
          errors={errors}
          defaultValues={defaultValues}
        />
      )
    }
  ];
... other code
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 MainComponent() {
  const {
    register,
    triggerValidation,
    defaultValues,
    errors,
    getValues
  } = useForm({
    // You can set default values here
    defaultValues: {
      uname: "Lol"
    }
  });
  console.log("Errors: ", errors);
  const [currentForm, setCurrentForm] = useState(0);

  // control password input visibility and Form1 fields
  const [passwordVisible, setPasswordVisible] = useState(false);

  const showPassword = () => {
    setPasswordVisible(true);
  };
  const hidePassword = () => {
    setPasswordVisible(false);
  };

  const forms = [
    {
      fields: passwordVisible
        ? ["uname", "email", "password"]
        : ["uname", "email"],
      component: (register, errors) => (
        <Form1
          // a key is needed to render a list
          key={0}
          // this will be used to set the css display property to block or none on each form
          shouldDisplay={currentForm === 0}
          register={register}
          errors={errors}
          showPassword={showPassword}
          hidePassword={hidePassword}
          passwordVisible={passwordVisible}
        />
      )
    },
    {
      fields: ["lname"],
      component: (register, errors) => (
        <Form2
          key={1}
          shouldDisplay={currentForm === 1}
          register={register}
          errors={errors}
        />
      )
    },
    {
      component: (register, errors) => (
        <Form3
          key={2}
          shouldDisplay={currentForm === 2}
          register={register}
          errors={errors}
          values={getValues()}
        />
      )
    }
  ];

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

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

  const prevButton = currentForm !== 0;
  const nextButton = currentForm !== forms.length - 1;
  const handleSubmit = e => {
    console.log("whole form data - ", getValues());
  };
  return (
    <div>
      <div className="progress">
        <div>{currentForm}</div>
      </div>

      {forms.map(form => form.component(register, errors))}

      {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 === 2 && (
        <button
          onClick={handleSubmit}
          className="btn btn-primary"
          type="submit"
        >
          Submit
        </button>
      )}
    </div>
  );
}

export default MainComponent;
import React,{useState}来自“React”;
从“/components/Form1”导入Form1;
从“/components/Form2”导入Form2;
从“/components/Form3”导入Form3;
从“react hook form”导入{useForm};
函数main component(){
常数{
登记
触发验证,
默认值,
错误,
获取值
}=使用形式({
//您可以在此处设置默认值
默认值:{
uname:“Lol”
}
});
日志(“错误:”,错误);
const[currentForm,setCurrentForm]=useState(0);
//控制密码输入可见性和Form1字段
const[passwordVisible,setPasswordVisible]=useState(false);
常量showPassword=()=>{
setPasswordVisible(true);
};
常量hidePassword=()=>{
setPasswordVisible(false);
};
常数形式=[
{
字段:passwordVisible
?[“uname”、“email”、“password”]
:[“uname”,“email”],
组件:(寄存器,错误)=>(
)
},
{
字段:[“lname”],
组件:(寄存器,错误)=>(
)
},
{
组件:(寄存器,错误)=>(
)
}
];
常量moveToPrevious=()=>{
triggerValidation(表单[currentForm].fields)。然后(valid=>{
如果(有效)setCurrentForm(currentForm-1);
});
};
常量moveToNext=()=>{
triggerValidation(表单[currentForm].fields)。然后(valid=>{
如果(有效)setCurrentForm(currentForm+1);
});
};
const prevButton=currentForm!==0;
const nextButton=currentForm!==forms.length-1;
常量handleSubmit=e=>{
log(“整个表单数据-”,getValues());
};
返回(
{currentForm}
{forms.map(form=>form.component(寄存器,错误))}
{prevButton&&(
返回
)}
{nextButton&&(
下一个
)}
{currentForm===2&&(
提交
)}
);
}
出口d
import React from "react";

function Form3({ values, shouldDisplay }) {
  return (
    <div style={{ display: shouldDisplay ? "block" : "none" }}>
      <h3>Want to display all values here like below</h3>
      {Object.entries(values).map(([key, value]) => (
        <p key={key}>
          {key}: {value}
        </p>
      ))}

      <br />
      <p>So that use can check for any Wrong info</p>
    </div>
  );
}

export default Form3;