如何使用反应以多步形式进行验证
Posted
技术标签:
【中文标题】如何使用反应以多步形式进行验证【英文标题】:How to give validation in multi step form using react 【发布时间】:2020-11-02 06:56:49 【问题描述】:我正在处理一个我已经完成的多步骤表单以及验证部分的场景。我正在使用react-hook-form
进行验证。
我有多步表格:
在第一种形式中,我有几个字段和一个单选按钮 默认情况下,auto generated pass
的单选按钮处于选中状态,所以在这种情况下,我无事可做
第二个是let me create a password
,所以在这种情况下,将显示一个输入字段,用户将创建密码
问题
在我的最终表单中,我正在进行如下验证:
fields: ["uname", "email", "password"], //to support multiple fields form
component: (register, errors, defaultValues) => (
<Form1
register=register
errors=errors
defaultValues=defaultValues
/>
)
,
所以为了验证 uname、email 和密码,我将传递上述值。
但是当勾选自动生成密码的单选按钮时,它仍在处理验证,我点击下一步,由于密码字段,它不会进入下一步。
如果我将单选按钮选中为let me create the password
,它会转到下一个表单,当我点击back
返回时,它会再次转到auto generated password
,它不会保持以前的状态。对于其他输入字段,它正在处理以前的值,但在单选按钮情况下不处理。
My full working code sandbox
【问题讨论】:
你看过这个视频吗:youtube.com/watch?v=CeAkxVwsyMU @Bill 已经是了,但是他们已经使用了路由,我没有为这个东西使用路由,我永远不应该使用它。 【参考方案1】:答案1 原因是你fields: ["uname", "email", "password"]
是固定的,password
总是要被验证的。
解决方案 需要将Form1
的状态保存在App 中,以便检查auto generated password
的状态是否为从列表中删除密码
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
答案 2 当你下一步时,Form1
被卸载,因此它的状态被破坏。当您将 Form1 的状态存储在 App.js 中时,您也将解决此问题
奖励:最好使用 camalCase(例如:showInput)而不是下划线(show_input)
【讨论】:
嘿,正在使用您的代码,但卡在了一个地方我提出了一个新问题,请您检查一下***.com/questions/64241134/hot-validate-react-form【参考方案2】:主要问题是您有条件地呈现表单,因此所有以前的表单值都被删除。解决方案是保持所有表单都已安装,并根据选择的表单使用display: none
或display: block
。这样,每当您转到下一个或上一个表单或提交表单时,所有值都将保持不变。
第二个问题是您在卸载时没有删除密码字段,因此当调用 moveToNext
时,triggerValidation
回调中的 valid
参数始终为 false。我通过根据密码输入是否可见有条件地设置 Form1 的字段来解决此问题。
您将defaultValues
用于错误目的的第三个问题。您可以使用getValues()
获取当前表单值,这将返回表单的所有当前值。
我将uname
字段的默认值设置为一个示例,向您展示如何使用defaultValues
。
您可以在此处查看完整的解决方案:https://codesandbox.io/s/fragrant-forest-75pzs?file=/src/App.js
这里是所有更改的文件:
App.js
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;
表格1
import React from "react";
function Form1(
register,
errors,
shouldDisplay,
passwordVisible,
showPassword,
hidePassword
)
return (
<div style= display: shouldDisplay ? "block" : "none" >
<form autoComplete="on">
<br />
<div className="form-group">
<label>User name</label>
<input type="text" name="uname" ref=register( required: true ) />
errors.uname && <span>required</span>
<label>Email</label>
<input type="email" name="email" ref=register( required: true ) />
errors.email && <span>required</span>
</div>
<div>
<div className="col-12 col-sm-12 col-md-12 col-lg-12 col-xl-12">
<label className="form_label">Password</label>
<div className="form-check">
<label>
<input
type="radio"
name="auto_pass"
id="Radios1"
value="auto_pass"
className="form-check-input"
defaultChecked=true
onChange=hidePassword
/>
Auto generated password
</label>
</div>
<div className="form-check">
<label>
<input
type="radio"
name="auto_pass"
id="Radios2"
value="let_me"
className="form-check-input"
onChange=showPassword
/>
Let me create the password
</label>
</div>
</div>
passwordVisible && (
<div className="col-12 col-sm-12 col-md-12 col-lg-12 col-xl-12 mb-3">
<label className="form_label">Password</label>
<input
type="password"
name="password"
className="form-control"
ref=register( required: true )
/>
errors.password && (
<span className="text-danger">Password is reguired</span>
)
</div>
)
</div>
</form>
</div>
);
export default Form1;
Form2
import React from "react";
function Form2( register, errors, shouldDisplay )
return (
<div style= display: shouldDisplay ? "block" : "none" >
<form autoComplete="on">
<br />
<div className="form-group">
<label>User last name</label>
<input type="text" name="lname" ref=register( required: true ) />
errors.lname && <span>required</span>
</div>
</form>
</div>
);
export default Form2;
Form3
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;
【讨论】:
以上是关于如何使用反应以多步形式进行验证的主要内容,如果未能解决你的问题,请参考以下文章