I need to validate multiple input fields using React. I am using a simple if-else block for each input field but I would like to optimize my code and make it better. I feel there can be a better way to validate multiple input fields.
validateForm = () => {
const {
firstName, lastName, mobileNo, city, empType, salary
} = this.state;
if (firstName !== '') {
this.setState({
firstNameMsg: '',
validFirstName: false
});
} else {
this.setState({
firstNameMsg: 'Please enter a vaild first name.',
validFirstName: true
});
}
if (lastName !== '') {
this.setState({
lastNameMsg: '',
validLastName: false
});
} else {
this.setState({
lastNameMsg: 'Please enter a vaild last name.',
validLastName: true
});
}
if (mobileNo.match(/^(\+\d{1,3}[- ]?)?\d{10}$/) && !(mobileNo.match(/0{5,}/))) {
this.setState({
mobileNoMsg: '',
validMobileNo: false
});
} else {
this.setState({
mobileNoMsg: 'Please enter a vaild mobile number.',
validMobileNo: true
});
}
if (city !== '') {
this.setState({
cityMsg: '',
validCity: false
});
} else {
this.setState({
cityMsg: 'Please enter a vaild city.',
validCity: true
});
}
if (empType !== 'Self-Employed') {
this.setState({
empTypeMsg: '',
validEmpType: false
});
} else {
this.setState({
empTypeMsg: 'Some msg',
validEmpType: true
});
}
if (salary !== '') {
this.setState({
salaryMsg: '',
validSalary: false
});
} else {
this.setState({
salaryMsg: 'Please enter a vaild salary.',
validSalary: true
});
}
}
1 Answer 1
Validation is so common that I recommend generalizing it a little bit (not too much though, there are too many special cases).
One way is to create validations, schema, and data separate from each other. For example:
const validators = {
required: (config, value) => value !== '',
mobileNo: (config, value) => value.match(/^(\+\d{1,3}[- ]?)?\d{10}$/) && !(value.match(/0{5,}/)),
equal: (config, value) => value === config.value
}
const validate = (data, schema) => {
const messages = {}
for(let [name, rules] of Object.entries(schema)){
for(let rule of rules){
if(!validators[rule.type](rule, data[name])){
if(!messages.hasOwnProperty(name)) messages[name] = []
messages[name].push(rule.msg)
}
}
}
return messages
}
const schema = {
firstName: [{type: 'required', msg: 'Please enter a valid first name.'}],
lastName: [{type: 'required', msg: 'Please enter a valid last name.'}],
mobileNo: [{type: 'required', msg: 'Please enter a mobile number'}, {type: 'mobileNo', msg: 'Please enter a valid mobile number.'}],
city: [{type: 'required', msg: 'Please enter a vaild city.'}],
empType: [{type: 'equal', value: 'Self-Employed', msg: 'Some msg'}],
salary: [{type: 'required', msg: 'Please enter a vaild salary.'}],
}
// In react component
validateForm(){
const validationMessages = validate(this.state.data, schema)
this.setState({validationMessages})
}
You can take this much further by adding templated validation messages, and fancy rules of all sorts. But I recommend keeping it simple. You can make multiple variants of the validate function for different needs as they come.
Explore related questions
See similar questions with these tags.
setState()
as well? \$\endgroup\$setState()
is native to react \$\endgroup\$