EDIT: As suggested by @bill I have personally used react-hook-form and I think it's great in terms of developer experience and simplicity. I would recommend using it.
You can write a separate module for form validation.
Validation module
import { emailRegex } from './regex'
export function validateEmail(email) {
if (!email.length) {
return {
status: true,
value: 'Email is required'
}
} else if (!emailRegex.test(email)) {
return {
status: true,
value: 'Email is invalid'
}
}
return {
status: false,
value: ''
}
}
export function validatePhone(phone) {
if (!phone.length) {
return {
status: true,
value: 'Mobile number is required'
}
} else if (isNaN(phone) || phone.length !== 10) {
return {
status: true,
value: 'Mobile number is invalid'
}
}
return {
status: false,
value: ''
}
}
This module will always return a object of signature { status, value }
. Where status is whether you want to show the error or not and value is the respective error message.
For example: if my email is invalid it will return { status: true, value: 'Email is invalid' }
Now in my react component I can simply import these validators and use it.
Form component
import { validateEmail, validatePhone } from './../validators'
class Form extends React.Component {
constructor() {
this.state = {
phoneErr: {
status: false,
value: ''
},
emailErr: {
status: false,
value: ''
}
}
}
handleSubmit() {
if(this.checkFormStatus()) {
// submit form
}
}
checkFormStatus() {
// form validation middleware
const { email, phone } = this.state
const emailErr = validateEmail(email)
const phoneErr = validatePhone(phone)
if (!emailErr.status && !phoneErr.status) {
return true
} else {
this.setState({
emailErr,
phoneErr
})
return false
}
}
render() {
return (
<div>
<div className="form-group">
<label>Member Phone Number</label>
<input
onChange={this.handleChange}
value={this.state.phone}
name="phone"
type="text"
maxLength={10}
/>
{ phoneErr.status && <p className="form-group__error">{ phoneErr.value }</p>}
</div>
<div className="form-group">
<label>Email Address</label>
<input
onChange={this.handleChange}
value={this.state.email}
name="email"
type="text"
/>
{ emailErr.status && <p className="form-group__error">{ emailErr.value }</p>}
</div>
<Button onClick={this.handleSubmit} primary>Add member</Button>
</div>
)
}
}
I have separated the checkFormStatus
function as a validation middleware.
The idea here is to separate the validation part from my react component. This way I have decoupled my form validation logic. I just need two things status
and message
. Now I can use my form validation in my other applications too.