How to Validate Forms in React
Use React form validation when input must be checked before submission, such as required fields, email formats, password rules, or business constraints. The cleanest pattern is controlled state plus validation inside the submit flow.
What you’ll build or solve
You’ll learn how to validate forms in React with controlled inputs, error state, and submit-time checks. You’ll also know how to scale this pattern to live validation.
Learn React on Mimo
When this approach works best
This approach is the right choice when the UI needs clear feedback before sending data to an API.
Common real-world scenarios include:
- Signup validation
- Checkout billing rules
- Password strength checks
- Required profile fields
- Contact forms
This is a bad idea when the form is extremely large and better handled by a dedicated validation library.
Prerequisites
You only need:
- A React component
- Controlled form state
- Basic
useState()knowledge
Step-by-step instructions
Step 1: Add form data and error state
Track both the field values and any validation messages.
JavaScript
import { useState } from "react";
function SignupForm() {
const [formData, setFormData] = useState({
email: "",
password: ""
});
const [errors, setErrors] = useState({});
function handleChange(event) {
const { name, value } = event.target;
setFormData((prev) => ({
...prev,
[name]: value
}));
}
function handleSubmit(event) {
event.preventDefault();
const nextErrors = {};
if (!formData.email) {
nextErrors.email = "Email is required";
}
if (formData.password.length < 8) {
nextErrors.password = "Password must be at least 8 characters";
}
setErrors(nextErrors);
if (Object.keys(nextErrors).length > 0) {
return;
}
console.log("Submit form");
}
return (
<form onSubmit={handleSubmit}>
<input
name="email"
value={formData.email}
onChange={handleChange}
/>
{errors.email && <p>{errors.email}</p>}
<input
name="password"
type="password"
value={formData.password}
onChange={handleChange}
/>
{errors.password && <p>{errors.password}</p>}
<button type="submit">Create account</button>
</form>
);
}
export default SignupForm;
This keeps validation predictable and easy to expand.
Step 2: Extract reusable validation logic
As forms grow, move checks into a helper.
JavaScript
function validate(formData) {
const errors = {};
if (!formData.email.includes("@")) {
errors.email = "Enter a valid email";
}
return errors;
}
Then call it inside submit.
JavaScript
const nextErrors = validate(formData);
This keeps the component easier to scan.
Step 3: Add live validation when needed
For better UX, validate on blur or change.
JavaScript
function handleBlur() {
setErrors(validate(formData));
}
This works well for email and password feedback.
What to look for:
- Store errors in state
- Validate before submit
- Prevent API calls when errors exist
- Shared validation helpers scale better
- Use live validation selectively
Examples you can copy
Required field
JavaScript
if (!formData.name) {
errors.name = "Name is required";
}
Email check
JavaScript
if (!formData.email.includes("@"))
Password length
JavaScript
if (formData.password.length < 8)
Common mistakes and how to fix them
Mistake 1: Validating after API submission
What the reader might do:
Submit first, then validate.
Why it breaks: invalid requests hit the backend unnecessarily.
Corrected approach:
Validate before the request.
Mistake 2: Replacing all errors with one string
What the reader might do:
Use one error state for the whole form.
Why it breaks: field-level feedback becomes harder.
Corrected approach:
Store errors by field key.
Mistake 3: Never clearing resolved errors
What the reader might do:
Set an error once and leave it forever.
Why it breaks: the UI still shows errors after the user fixes the field.
Corrected approach:
Revalidate on change or blur.
Troubleshooting
If errors never disappear, revalidate on field change.
If the form still submits invalid data, stop the flow when errors exist.
If field messages show in the wrong place, align error keys with field names.
If the form grows complex, consider React Hook Form plus schema validation.
Quick recap
- Store form data and errors in state
- Validate before submit
- Use field-level error keys
- Extract reusable validation helpers
- Revalidate on change or blur when helpful
Join 35M+ people learning for free on Mimo
4.8 out of 5 across 1M+ reviews
Check us out on Apple AppStore, Google Play Store, and Trustpilot