100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
React

Form Validation in React

Implement client-side validation logic for React forms, including error state and submit-time checks.

Forms & EventsIntermediate10 min readJul 8, 2026
Analogies

Introduction

Form validation ensures users provide correct, complete data before it is submitted to a server. In React, validation is typically implemented by tracking an errors object alongside your form state, running validation logic either on every change, on blur, or on submit, and conditionally rendering error messages based on that errors object. This gives users immediate, clear feedback and prevents unnecessary network requests with invalid data. While libraries like Formik, React Hook Form, and Yup exist for complex forms, understanding manual validation with plain useState is essential.

🏏

Cricket analogy: Before a scorecard is submitted to the league, an umpire's checklist (errors state) flags issues like a mismatched player count, checked on every ball, at the innings break, or only at match end; while apps like DRS exist for complex reviews, a manual checklist with plain notes is essential.

Syntax

jsx
function validateEmail(value) {
  if (!value) return 'Email is required';
  if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value)) return 'Email is invalid';
  return '';
}

const [errors, setErrors] = useState({});

Explanation

A common pattern is to keep an errors state object shaped like the form data, where each key holds an error message string (or empty string when valid). Validation functions take a field's value and return an error message or an empty string. You can run validation on every onChange for instant feedback, on onBlur so errors don't flash while the user is still typing, or only on submit to avoid being intrusive. On submit, you validate every field, collect all errors into one object, call setErrors with the result, and only proceed with the actual submission (e.g. an API call) if the resulting errors object has no truthy values.

🏏

Cricket analogy: The errors object mirrors the scorecard's shape, a key for 'runs' and a key for 'wickets', each holding a message or empty string; you check runs on every ball (onChange), wickets when the over ends (onBlur), or only at innings-end (onSubmit), proceeding to declare only if every key is empty.

Example

jsx
function SignupForm() {
  const [formData, setFormData] = useState({ email: '', password: '' });
  const [errors, setErrors] = useState({});

  function validate(data) {
    const newErrors = {};
    if (!data.email) newErrors.email = 'Email is required';
    if (data.password.length < 8) newErrors.password = 'Password must be at least 8 characters';
    return newErrors;
  }

  function handleSubmit(event) {
    event.preventDefault();
    const newErrors = validate(formData);
    setErrors(newErrors);
    if (Object.keys(newErrors).length === 0) {
      console.log('Form is valid, submitting:', formData);
    }
  }

  function handleChange(event) {
    const { name, value } = event.target;
    setFormData((prev) => ({ ...prev, [name]: value }));
  }

  return (
    <form onSubmit={handleSubmit} noValidate>
      <input name="email" value={formData.email} onChange={handleChange} />
      {errors.email && <span role="alert">{errors.email}</span>}
      <input name="password" type="password" value={formData.password} onChange={handleChange} />
      {errors.password && <span role="alert">{errors.password}</span>}
      <button type="submit">Sign Up</button>
    </form>
  );
}

Output

If the user submits with an empty email or a password shorter than 8 characters, handleSubmit populates the errors object and the corresponding <span role="alert"> messages render below each invalid field, while the console.log for a valid submission never runs. Once the user corrects the fields and resubmits, newErrors is an empty object, the error spans disappear, and the form data is logged.

🏏

Cricket analogy: Submitting a team sheet with a missing captain field or fewer than 11 named players populates errors, and alert messages render below those fields while the 'Team confirmed' log never fires; once corrected, newErrors is empty, the alerts disappear, and the lineup is logged.

Key Takeaways

  • Track validation errors in a dedicated errors state object shaped like the form data.
  • Validation functions return an error message string, or an empty string/undefined when the value is valid.
  • Run validation on submit at minimum; onChange or onBlur validation adds immediate feedback but can feel intrusive if overused.
  • Only proceed with submission logic when the computed errors object has no entries.
  • Add noValidate to <form> when you want to fully control validation UI instead of relying on native browser tooltips.

Practice what you learned

Was this page helpful?

Topics covered

#React#ReactJsStudyNotes#WebDevelopment#FormValidationInReact#Form#Validation#Syntax#Explanation#StudyNotes#SkillVeris