Validation is really important when it comes to frontend form implementation. You should never trust the user input, so you should validate that the information provided by the user is exactly what your application is expected.
There is a couple of libraries out there that help with form validation, but today I'll introduce a small and simple one called js-flex-validator
, that allows you to quickly implement React form validation with real-time custom error messages.
First install the library using yarn
or npm
in your react project:
With
npm
npm install js-flex-validator
With
yarn
yarn add js-flex-validator
Now to show you how to use the library, we'll create a simple form like this one, with a username
, email
and password
field:
See it live on CodeSandbox here
1- First, let's import the library Flex
and the utility functions validateObject, validateValue
from js-flex-validator
:
import Flex, { validateObject, validateValue } from "js-flex-validator";
2- Now, let's define the constraints for the username
, email
and password
field of our form:
const constraints = {
username: Flex("username")
.string()
.required()
.allowEmpty()
.min(3, "Username should be at least 3 characters")
.max(50, "Username should not exceeds 50 characters"),
email: Flex("email")
.email("This email is not valid.")
.match(/\w.@edu.com$/, "Should be an email with a edu.com domain")
.required()
.min(5, "Email should be at least 3 characters")
.max(255, "Email should not exceeds 255 characters"),
password: Flex("password")
.string()
.required()
.min(8, "Password should be at least 8 characters")
.max(20, "Password should not exceeds 20 characters")
.match(
/^(?=.*[A-Z])(?=.*[!@#$&*])(?=.*[0-9])(?=.*[a-z])/,
"Should have at least 1 special character, 1 uppercase letter and 1 number"
)
};
3- Next, we define two functions, validateState
and validateField
. The validateState
function is to validate our whole state object, that will have the username
, email
and password
when the form is submitted. The validateField
function is to validate each field individually as the user is filling the form.
const validateState = (state) => {
const constraintsArr = Object.values(constraints);
const { hasError } = validateObject(state, constraintsArr);
return hasError;
};
const validateField = (name, value) => {
const fieldConstraint = constraints[name];
const message = validateValue(value, fieldConstraint);
return message;
};
4- Next, we implement our form (I assume you are familiar with react and know how to implement a form). For each input field, we make use of the validateField
function, passing it the field value that we want to validate, and the constraint of this specific field, getting it from the constraints object that we defined earlier. Then we get the result of the validation, and set an errors
object, if there is an error.
Then when the form is submitted, we make use of the validateState
function to make sure that all fields are valid, before submitting the form.
const initialState = {
username: "",
password: "",
email: ""
};
export default function App() {
const [state, setState] = React.useState(initialState);
const [errors, setErrors] = React.useState(null);
const handleSubmit = (e) => {
e.preventDefault();
// Validate if all fields in the state are valid, if not, return.
const error = validateState(state);
if (error) return;
// If all fields are valid, process the data
console.log(state);
};
const handleChange = (e) => {
const { name, value } = e.target;
// set state, with the value entered by the user
setState({
...state,
[name]: value.trim()
});
// check if value entered by user is valid
const fieldError = validateField(name, value.trim());
// Set errors if any
if(fieldError){
setErrors({
...errors,
[name]: fieldError
});
}
};
return (
<form className="App" onSubmit={handleSubmit}>
<h2>React Form Validation</h2>
<h4>With JS-flex-validator</h4>
<div>
<input
name="username"
type="text"
placeholder="Username"
value={state.username}
onChange={handleChange}
/>
{errors && <small>{errors.username}</small>}
</div>
<div>
<input
name="email"
type="text"
placeholder="Email"
value={state.email}
onChange={handleChange}
/>
{errors && <small>{errors.email}</small>}
</div>
<div>
<input
name="password"
type="password"
placeholder="Password"
value={state.password}
onChange={handleChange}
/>
{errors && <small>{errors.password}</small>}
</div>
<div>
<button disabled={validateState(state)} type="submit">
submit
</button>
</div>
</form>
);
}
Here is the full and simplified code, that implements the real-time validation using js-flex-validator
import React from "react";
import Flex, { validateObject, validateValue } from "js-flex-validator";
import "./styles.css";
const constraints = {
username: Flex("username")
.string()
.required()
.allowEmpty()
.min(3, "Username should be at least 3 characters")
.max(50, "Username should not exceeds 50 characters"),
email: Flex("email")
.email("This email is not valid.")
.match(/\w.@edu.com$/, "Should be an email with a edu.com domain")
.required()
.min(5, "Email should be at least 3 characters")
.max(255, "Email should not exceeds 255 characters"),
password: Flex("password")
.string()
.required()
.min(8, "Password should be at least 8 characters")
.max(20, "Password should not exceeds 20 characters")
.match(
/^(?=.*[A-Z])(?=.*[!@#$&*])(?=.*[0-9])(?=.*[a-z])/,
"Should have at least 1 special character, 1 uppercase letter and 1 number"
)
};
const validateState = (state) => {
const constraintsArr = Object.values(constraints);
const { hasError } = validateObject(state, constraintsArr);
return hasError;
};
const validateField = (name, value) => {
const fieldConstraint = constraints[name];
const message = validateValue(value, fieldConstraint);
return message;
};
const initialState = { username: "", password: "", email: "" };
export default function App() {
const [state, setState] = React.useState(initialState);
const [errors, setErrors] = React.useState(null);
const handleSubmit = (e) => {
e.preventDefault();
const error = validateState(state);
if (error) return;
console.log(state);
};
const handleChange = (e) => {
const { name, value } = e.target;
setState({ ...state, [name]: value.trim() });
setErrors({ ...errors, [name]: validateField(name, value.trim()) });
};
return (
<form className="App" onSubmit={handleSubmit}>
<h2>React Form Validation</h2>
<h4>With JS-flex-validator</h4>
<div>
<input
name="username"
type="text"
placeholder="Username"
value={state.username}
onChange={handleChange}
/>
{errors && <small>{errors.username}</small>}
</div>
<div>
<input
name="email"
type="text"
placeholder="Email"
value={state.email}
onChange={handleChange}
/>
{errors && <small>{errors.email}</small>}
</div>
<div>
<input
name="password"
type="password"
placeholder="Password"
value={state.password}
onChange={handleChange}
/>
{errors && <small>{errors.password}</small>}
</div>
<div>
<button disabled={validateState(state)} type="submit">
submit
</button>
</div>
</form>
);
}
Hope this helps.
Happy coding!
Top comments (0)