Form validation means checking user-entered data before processing or submitting a form. In React, validation can be performed using state, event handlers, conditions, and validation functions.
Form validation checks whether the information entered by the user meets the required rules.
For example:
Validation improves the quality of data collected from users and provides useful feedback when information is missing or incorrect.
A simple validation check can determine whether a field is empty.
if (name === "") {
alert("Name is required");
return;
}
The form can stop processing when the required value is missing.
Validation can be performed inside the form submission handler.
function handleSubmit(e) {
e.preventDefault();
if (name === "") {
alert("Please enter your name");
return;
}
console.log("Form submitted");
}
Instead of displaying an alert, an error message can be stored in React state.
const [error, setError] = useState("");
function handleSubmit(e) {
e.preventDefault();
if (name === "") {
setError("Name is required");
return;
}
setError("");
}
The error state can be displayed conditionally.
{error && (
<p>
{error}
</p>
)}
The message appears when error contains a value.
const [name, setName] = useState("");
const [error, setError] = useState("");
function handleSubmit(e) {
e.preventDefault();
if (name.trim() === "") {
setError("Name is required");
return;
}
setError("");
}
Using trim() helps detect input containing only spaces.
An email field can be checked before the form is submitted.
if (email.trim() === "") {
setError("Email is required");
return;
}
Additional checks can be used when a particular email format is required.
A regular expression can be used for a basic email format check.
const emailPattern =
/^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailPattern.test(email)) {
setError("Enter a valid email address");
return;
}
A password can be checked for a minimum length.
if (password.length < 6) {
setError(
"Password must be at least 6 characters"
);
return;
}
A form can contain multiple validation rules.
if (name.trim() === "") {
setError("Name is required");
return;
}
if (email.trim() === "") {
setError("Email is required");
return;
}
if (password.length < 6) {
setError(
"Password must be at least 6 characters"
);
return;
}
For larger forms, errors can be stored in an object.
const [errors, setErrors] = useState({
name: "",
email: "",
password: ""
});
Each property can contain the validation message for one field.
A separate function can keep validation logic organized.
function validateForm() {
if (name.trim() === "") {
return "Name is required";
}
if (email.trim() === "") {
return "Email is required";
}
return "";
}
function handleSubmit(e) {
e.preventDefault();
const message = validateForm();
if (message) {
setError(message);
return;
}
setError("");
console.log("Form submitted");
}
A required field should contain a meaningful value before submission.
<input
type="text"
value={name}
onChange={(e) =>
setName(e.target.value)
}
required
/>
HTML validation can also provide a basic browser-level required check. React applications can additionally implement their own validation logic.
A minimum length rule can be used for fields such as passwords.
if (password.length < 8) {
setError(
"Password must contain at least 8 characters"
);
return;
}
A maximum length rule can prevent unnecessarily long input.
if (name.length > 50) {
setError(
"Name cannot exceed 50 characters"
);
return;
}
Numeric values can be checked against minimum and maximum limits.
const ageNumber = Number(age);
if (ageNumber < 18) {
setError(
"Age must be at least 18"
);
return;
}
A confirm password field can be compared with the original password.
if (password !== confirmPassword) {
setError("Passwords do not match");
return;
}
<input
type="text"
value={name}
onChange={(e) =>
setName(e.target.value)
}
/>
{errors.name && (
<p>
{errors.name}
</p>
)}
Displaying the message close to the related field makes the error easier to understand.
Validation can also be performed while the user types.
function handleNameChange(e) {
const value = e.target.value;
setName(value);
if (value.trim() === "") {
setError("Name is required");
} else {
setError("");
}
}
The onBlur event runs when an input loses focus. It can
be used to validate a field after the user leaves it.
function validateName() {
if (name.trim() === "") {
setError("Name is required");
} else {
setError("");
}
}
<input
value={name}
onChange={(e) =>
setName(e.target.value)
}
onBlur={validateName}
/>
const [form, setForm] = useState({
name: "",
email: "",
password: ""
});
function validateForm() {
const errors = {};
if (!form.name.trim()) {
errors.name = "Name is required";
}
if (!form.email.trim()) {
errors.email = "Email is required";
}
if (form.password.length < 6) {
errors.password =
"Password must contain at least 6 characters";
}
return errors;
}
function handleSubmit(e) {
e.preventDefault();
const validationErrors = validateForm();
setErrors(validationErrors);
if (Object.keys(validationErrors).length > 0) {
return;
}
console.log("Form submitted");
}
Object.keys() can be used to determine whether the errors
object contains any validation errors.
import { useState } from "react";
function App() {
const [form, setForm] = useState({
name: "",
email: "",
password: ""
});
const [errors, setErrors] = useState({});
function handleChange(e) {
setForm({
...form,
[e.target.name]: e.target.value
});
}
function validateForm() {
const errors = {};
if (!form.name.trim()) {
errors.name = "Name is required";
}
if (!form.email.trim()) {
errors.email = "Email is required";
}
if (form.password.length < 6) {
errors.password =
"Password must contain at least 6 characters";
}
return errors;
}
function handleSubmit(e) {
e.preventDefault();
const validationErrors = validateForm();
setErrors(validationErrors);
if (Object.keys(validationErrors).length === 0) {
alert("Registration successful");
}
}
return (
<form onSubmit={handleSubmit}>
<input
name="name"
value={form.name}
onChange={handleChange}
placeholder="Name"
/>
{errors.name && (
<p>{errors.name}</p>
)}
<input
name="email"
value={form.email}
onChange={handleChange}
placeholder="Email"
/>
{errors.email && (
<p>{errors.email}</p>
)}
<input
type="password"
name="password"
value={form.password}
onChange={handleChange}
placeholder="Password"
/>
{errors.password && (
<p>{errors.password}</p>
)}
<button type="submit">
Register
</button>
</form>
);
}
export default App;
A form should not be processed when required validation rules fail.
function handleSubmit(e) {
e.preventDefault();
const errors = validateForm();
if (Object.keys(errors).length > 0) {
setErrors(errors);
return;
}
submitForm();
}
The actual submission logic runs only after validation succeeds.
When a user corrects a field, its error message can be cleared.
function handleNameChange(e) {
const value = e.target.value;
setForm({
...form,
name: value
});
if (value.trim()) {
setErrors({
...errors,
name: ""
});
}
}
React can perform client-side validation before sending data to a server.
However, important application data should also be validated on the server because client-side validation alone should not be treated as a security boundary.
React Form
↓
Client Validation
↓
Server Request
↓
Server Validation
↓
Process Data
A common React form validation workflow is:
User Input
↓
React State
↓
Submit Form
↓
Validate
↓
Errors?
↙ ↘
Yes No
↓ ↓
Show Process
Errors Data
trim() when checking text fields where appropriate.Question: What is the main purpose of form validation in React?