我为多个输入创建了表单,其中特定输入数据应在数据输入时进行验证,并在表单提交到后端之前再次对所有数据进行验证。
要提交的条件:所有字段都是必填字段,数据有效。
我的程序有效,但我不喜欢我在2个地方重复验证码:ErrorOutput和hadleSubmit。
在ErrorOutput中,我检查数据,如有必要,显示错误消息
在handleSubmit中,我只检查数据而不显示错误消息,如果所有数据都有效,我确认提交。
如何改进我的示例以防止重复此代码,但数据验证也是在数据输入时和提交之前?
{{1}}
答案 0 :(得分:2)
您可以提取FormItem
组件:
class FormItem extends React.Component {
render() {
return (
<div>
<label>
{this.props.label}
</label>
<input
{...this.props.input}
/>
<ErrorOutput
case={this.props.input.value}
name={this.props.input.name}
submit={this.props.onSubmit}
/>
</div>
);
}
}
并在App
:
render() {
return (
<form onSubmit={this.handleSubmit.bind(this)}>
<FormItem label='First name:' input={{
type: 'text'
name: 'firstName'
value: this.state.firstName,
onChange: this.handleValidation.bind(this)
}}
onSubmit={this.state.submit}
/>
<FormItem label='Phone number:' input={{
type:'tel'
name :'telNo'
value : {this.state.telNo}
onChange : {this.handleValidation.bind(this)}
}}
onSubmit={this.state.submit}
/>
<button>
Submit
</button>
</form>
)
}
这就是像react-final-form和redux-form这样的图书馆变得方便的地方。
ErrorOutput
组件不应该验证任何内容,它不是组件的责任。相反,您可以在输入模糊事件和提交之前验证您的值:
class App extends React.Component {
constructor(props){
super(props)
this.state = {
firstName: '',
telNo: '',
submit: false,
errors: {},
invalid: false,
}
}
handleSubmit(e){
e.preventDefault()
if (this.validate()) {
// handle error
} else {
// submit
}
}
validate = () => {
const { firstName, telNo } = this.state
const errors = {}
let invalid = false;
if (firstName === '' || !firstName.match(/^[a-zA-Z]+$/)) {
errors.firstName = 'first name is required'
invalid = true;
} else if (telNo === '' || !telNo.match(/^[0-9]+$/)) {
telNo.telNo = 'telNo is required'
invalid = true;
}
this.setState({
invalid,
errors,
})
return invalid;
}
render() {
return (
<form onSubmit={this.handleSubmit.bind(this)}>
<FormItem label='First name:' input={{
type: 'text',
name: 'firstName',
value: this.state.firstName,
onChange: e => this.setState({ firstName: e.target.value }),
onBlur: () => this.validate(),
}}
/>
<FormItem label='Phone number:' input={{
type: 'tel',
name: 'telNo',
value: this.state.telNo,
onChange: e => this.setState({ telNo: e.target.value }),
onBlur: () => this.validate(),
}}
/>
<button>
Submit
</button>
</form>
)
}
}
和FormItem和ErrorOutput:
const ErrorOutput = ({ error }) => <span>{error}</span>
class FormItem extends React.Component {
render() {
return (
<div>
<label>
{this.props.label}
</label>
<input
{...this.props.input}
/>
{this.props.error && <ErrorOutput error={this.props.error} />}
</div>
);
}
}
答案 1 :(得分:2)
const ErrorOutput = ({ errorText }) => <span>{errorText}</span>;
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
firstName: "",
telNo: "",
submit: false,
errors: {} //Add errors object to the state.
};
}
handleSubmit(e) {
e.preventDefault();
const errors = this.validateData();
if (Object.keys(errors).length === 0) {
alert("Success");
}
//else errors exist
this.setState({ errors });
}
validateData = () => {
let errors = {};
const { firstName, telNo } = this.state; // read the values to validate
if (firstName.length === 0) {
errors.firstName = "Required";
} else if (firstName.length > 0 && !firstName.match(/^[a-zA-Z]+$/)) {
errors.firstName = "Letters only";
}
if (telNo.length === 0) {
errors.telNo = "Required";
} else if (telNo.length > 0 && !telNo.match(/^[0-9]+$/)) {
errors.telNo = "Numbers only";
}
return errors;
};
handleValidation(e) {
this.setState({
[e.target.name]: e.target.value
});
}
render() {
const { errors } = this.state; // read errors from the state
return (
<form onSubmit={this.handleSubmit.bind(this)}>
<div>
<label>First name:</label>
<input
type="text"
name="firstName"
value={this.state.firstName}
onChange={this.handleValidation.bind(this)}
/>
{errors.firstName && <ErrorOutput errorText={errors.firstName} />}
</div>
<div>
<label>Phone number:</label>
<input
type="tel"
name="telNo"
value={this.state.telNo}
onChange={this.handleValidation.bind(this)}
/>
{errors.telNo && <ErrorOutput errorText={errors.telNo} />}
</div>
<button>Submit</button>
</form>
);
}
}
render(<App />, document.getElementById("root"));