Javascript React JS表单验证逻辑位于子级还是父级?
我不确定我是否理解如何组织我的第一个React JS应用程序,比如简单的验证逻辑。我的想法是将尽可能多的逻辑放在每个子组件中,但在我看来,更符合逻辑的地方是父组件。但这对我来说似乎是错误的,因为家长最终可能会为所有孩子编写大量代码。我已经包括了一个真正简单的例子来说明这个问题 在我的示例代码中,有一个用于输入框的小的子组件,一个中间组件包含两个输入框(我们称之为用户名控件),然后顶部组件是一个编辑页面。每个组件都有自己版本的Javascript React JS表单验证逻辑位于子级还是父级?,javascript,reactjs,react-native,Javascript,Reactjs,React Native,我不确定我是否理解如何组织我的第一个React JS应用程序,比如简单的验证逻辑。我的想法是将尽可能多的逻辑放在每个子组件中,但在我看来,更符合逻辑的地方是父组件。但这对我来说似乎是错误的,因为家长最终可能会为所有孩子编写大量代码。我已经包括了一个真正简单的例子来说明这个问题 在我的示例代码中,有一个用于输入框的小的子组件,一个中间组件包含两个输入框(我们称之为用户名控件),然后顶部组件是一个编辑页面。每个组件都有自己版本的isValid。最低的子级验证输入在有效之前是否为空。中间组件验证两个输
isValid
。最低的子级验证输入在有效之前是否为空。中间组件验证两个输入框是否包含内容。顶部的父编辑页面与中间的组件执行相同的操作。我的问题是,存储这个简单验证逻辑的“理想”位置或级别是什么
提前考虑顶层编辑页面,该页面有一个简单的按钮,只有在选中所有验证时才应启用该按钮。这让我感到困惑的是,如果您使用各种规则管理表单上的许多部分。因此,不仅用户名部分需要有效,其他几个部分也需要有效
我的主要困惑是,我认为我遗漏了一些简单的东西,因为当涉及到顶部组件(编辑页面)上的按钮时,我认为中间组件(用户控件)无法传达其验证状态,除非我使用引用。在阅读了一些参考资料之后,它们似乎并没有被过度使用。如果编辑页面无法从验证的子用户名控件获得反馈,则父用户需要执行验证。对于大型表单,这意味着在父编辑页面中存储了大量验证逻辑。这可能是正常的,我只是不确定
有人能在我概述的场景中验证放置简单的“正确”位置是否有效吗
class InputBox extends React.Component {
constructor(props) {
super(props);
this.handleInputChange = this.handleInputChange.bind(this);
}
handleInputChange(e) {
this.props.onChange(e);
}
render() {
const inputValue = this.props.value;
const inputName = this.props.name;
const isValid = this.props.isValid;
const label = this.props.label;
const msg = isValid === true ? 'true' : 'false';
return (
<div>
<span>{label}</span>
<input type="text"
name={inputName}
value={inputValue}
onChange={this.handleInputChange} />
<span>Is this textbox valid = {msg}</span>
</div>
)}
}
class UserNameControl extends React.Component {
constructor(props) {
super(props);
this.handleChange = this.handleChange.bind(this);
}
handleChange(e) {
const controlName = e.target.name;
const newValue = e.target.value;
const inputValue1 = controlName === 'input1' ? newValue : this.props.value1;
const inputValue2 = controlName === 'input2' ? newValue : this.props.value2;
const isValid = inputValue1 === '' || inputValue2 === '' ? false : true;
this.props.onChange(controlName,newValue,isValid);
}
render() {
const inputValue1 = this.props.value1;
const inputValue2 = this.props.value2;
const isTextValid1 = inputValue1 === '' ? false : true;
const isTextValid2 = inputValue2 === '' ? false : true;
const msg1 = isTextValid1 === true ? 'true' : 'false';
const msg2 = isTextValid2 === true ? 'true' : 'false';
const isSectionValidMsg = inputValue1 === '' || inputValue2 === '' ? 'false' : 'true';
const isValid = inputValue1 === '' || inputValue2 === '' ? false : true;
//this.props.isValid(isValid);
return (
<div>
<div><h2>User Name Control Header</h2></div>
<InputBox
label='First Name: '
name='input1'
value={inputValue1}
isValid={isTextValid1}
onChange={this.handleChange}/>
<br/>
<InputBox
label='Last Name: '
name='input2'
value={inputValue2}
isValid={isTextValid2}
onChange={this.handleChange}/>
<div>
<h4>User Name Control Footer: Is section valid = {isSectionValidMsg}</h4>
</div>
</div>
)}
}
class EditPage extends React.Component {
constructor(props) {
super(props);
this.state = {
pageIsValid: false,
textValue1: '',
textValue2: '',
section1Valid: false
};
this.handleChange = this.handleChange.bind(this);
this.updateSection1Status = this.updateSection1Status.bind(this);
}
updateSection1Status(boolValue) {
this.setState({section1Valid: boolValue});
}
handleChange(controlName,inputValue,isSectionValid) {
this.setState({section1Valid: isSectionValid});
if(controlName==='input1') {
this.setState({textValue1: inputValue});
}
if(controlName==='input2') {
this.setState({textValue2: inputValue});
}
}
render() {
const isFormValid = this.state.textValue1 === '' || this.state.textValue2 === '' ? false : true;
//const formValidMsg = isFormValid ? 'True' : 'False';
const formValidMsg = this.state.section1Valid ? 'True' : 'False';
return (
<form>
<h1>Edit Form</h1>
<div>
<UserNameControl
value1={this.state.textValue1}
value2={this.state.textValue2}
onChange={this.handleChange}
/>
</div>
<div>
<h4>Is form valid = {formValidMsg}</h4>
</div>
</form>
);
}
}
ReactDOM.render(
<EditPage/>,
document.getElementById('root')
);
类InputBox扩展了React.Component{
建造师(道具){
超级(道具);
this.handleInputChange=this.handleInputChange.bind(this);
}
handleInputChange(e){
此.props.onChange(e);
}
render(){
const inputValue=this.props.value;
const inputName=this.props.name;
const isValid=this.props.isValid;
常量标签=this.props.label;
const msg=isValid==true?'true':'false';
返回(
{label}
此文本框是否有效={msg}
)}
}
类UserNameControl扩展了React.Component{
建造师(道具){
超级(道具);
this.handleChange=this.handleChange.bind(this);
}
手变(e){
const controlName=e.target.name;
const newValue=e.target.value;
常量inputValue1=controlName=='input1'?新值:this.props.value1;
常量inputValue2=controlName=='input2'?新值:this.props.value2;
常量isValid=inputValue1==''| | inputValue2==''?false:true;
this.props.onChange(controlName,newValue,isValid);
}
render(){
const inputValue1=this.props.value1;
const inputValue2=this.props.value2;
const isTextValid1=inputValue1==''?false:true;
const isTextValid2=inputValue2==''?false:true;
常量msg1=isTextValid1==true?'true':'false';
常量msg2=isTextValid2==true?'true':'false';
const IsSectionValidMg=inputValue1==''| | inputValue2==''假':'真';
常量isValid=inputValue1==''| | inputValue2==''?false:true;
//this.props.isValid(isValid);
返回(
用户名控制头
用户名控件页脚:节是否有效={IsSectionValidMg}
)}
}
类EditPage扩展了React.Component{
建造师(道具){
超级(道具);
此.state={
pageIsValid:false,
textValue1:“”,
textValue2:“”,
第1节有效:错误
};
this.handleChange=this.handleChange.bind(this);
this.updateSection1Status=this.updateSection1Status.bind(this);
}
updateSection1Status(布尔值){
this.setState({section1Valid:boolValue});
}
handleChange(controlName、inputValue、isSectionValid){
this.setState({section1Valid:isSectionValid});
如果(controlName==='input1'){
this.setState({textValue1:inputValue});
}
如果(controlName==='input2'){
this.setState({textValue2:inputValue});
}
}
render(){
const isFormValid=this.state.textValue1==''this.state.textValue2==''?false:true;
//const formvalidsg=isFormValid?'True':'False';
const formvalidsg=this.state.section1Valid?'True':'False';
返回(
编辑表格
form valid={FormValidMg}
);
}
}
ReactDOM.render(
,
document.getElementById('root'))
);
我认为您走的是正确的道路,父级应该处理大部分验证,因为这使子输入变得更通用,因此在整个应用程序中更可重用。在这个特定场景中,我认为子组件应该尽可能通用,中间组件应该处理大部分验证逻辑,并将结果传递给父组件。然而,在这种情况下,您可能还需要在父级进行验证,但老实说,整个过程可能只重构为两个组件,而不是三个。以下是我将如何处理您的场景:
import React from 'react'
const notEmptyValidation = value => Boolean(value)
const InputBox = props => {
const {validation, label, name} = props;
const [localValue, setValue] = React.useState(props.value||"");
const onChange = e => {
setValue(e.target.value);
if(typeof props.onChange === "function"){
return props.onChange(e)
}
}
const isValid = () => {
if(typeof validation === "function"){
return validation(localValue)
}
return true
}
React.useEffect(() => {
//this allows the component to be used as either a controlled or uncontrolled input
setValue(props.value||"")
}, [props.value])
return (
<div>
<span>{label}</span>
<input type="text"
name={name}
value={localValue}
onChange={onChange} />
<span>Is this textbox valid = {`${isValid() ? "true":"false"}`}</span>
</div>
)
}
const UserNameControl = props => {
const [input, setInput] = React.useState({
input1: "",
input2: ""
})
const onChange = e => {
let localInput = {...input}; //need to create a new reference to input state
localInput[e.target.name] = e.target.value
setInput(localInput)
if(typeof props.onChange === "function"){ //run the onChange callback from parent
return props.onChange(localInput)
}
}
//validates that all values in the input state are populated
const isValid = () => Object.keys(input).every(key => notEmptyValidation(input[key]))
return (
<div>
<div><h2>User Name Control Header</h2></div>
<InputBox
label='First Name: '
name='input1'
value={input.inputValue1}
validation={notEmptyValidation} //pass validation function down to the child
onChange={onChange}/>
<br/>
<InputBox
label='Last Name: '
name='input2'
value={input.inputValue2}
validation={notEmptyValidation} //pass validation function down to the child
onChange={onChange}/>
<div>
<h4>User Name Control Footer: Is section valid = {`${isValid() ? "true":"false"}`}.</h4>
</div>
</div>
)
}
const EditPage = () => {
const [userNameData, setUserNameData] = React.useState(null)
const onChange = inputObj => setUserNameData(inputObj)
//validates that the input was successful, and all entries are populated
const isValid = () => userNameData && Object.keys(userNameData).every(key => notEmptyValidation(userNameData[key]))
return (
<form>
<h1>Edit Form</h1>
<div>
<UserNameControl onChange={onChange}/>
</div>
<div>
<h4>Is form valid = {`${isValid() ? "true":"false"}`}</h4>
</div>
</form>
);
}
ReactDOM.render(
<EditPage/>,
document.getElementById('root')
);
从“React”导入React
const notEmptyValidation=value=>Boolean(值)
常量输入框=道具=>{
const{validation,label,name}=props;
const[localValue,setValue]=React.useState(props.value | | |“”);
const onChange=e=>{
设定值(即目标值);
if(公共关系类型)