Skip to content

Form Validation

Validation ensures users submit correct, complete data before it hits your API. React forms validate on change, on blur, or on submit. This lesson covers patterns from simple inline checks to schema-based validation with Zod.

Validation Strategies

Client-side validation improves UX with immediate feedback. Server-side validation remains mandatory for security — never trust the client alone.

Popular approaches: HTML5 attributes (required, pattern), custom functions, and schema libraries like Zod or Yup integrated with React Hook Form.

import { z } from 'zod';

const schema = z.object({
  email: z.string().email('Invalid email'),
  age: z.number().min(18, 'Must be 18+'),
});

function validate(form) {
  const result = schema.safeParse(form);
  return result.success ? {} : result.error.flatten().fieldErrors;
}

Zod schemas double as TypeScript type sources with z.infer<typeof schema>.

Showing Validation Errors

{errors.email && (
  <p id="email-error" role="alert">{errors.email}</p>
)}
<input
  aria-invalid={!!errors.email}
  aria-describedby="email-error"
  ...
/>
  • Display errors near the relevant field.
  • Use role="alert" for important error messages.
  • Connect inputs with aria-describedby for screen readers.
  • Validate on submit at minimum; on blur for early feedback.

Validation Approaches

Compare validation methods in React apps.

Method Pros
HTML5 constraints Zero JS, native browser UI
Manual functions Full control, simple forms
Zod / Yup schemas Reusable, type-safe rules
React Hook Form + Zod Performance + schema validation
Server errors Authoritative, security
Async validation Check username availability

When to Validate

On submit validation avoids annoying users while typing. On blur catches errors field-by-field. On change enables live feedback but can feel aggressive — use for password strength meters, not every field.

Timing Best For
onSubmit Most forms, required baseline
onBlur Email format, field-level checks
onChange Password strength, character limits
Server round-trip Unique username, credit checks

Displaying Server Validation Errors

APIs often return field-specific errors after submit. Map server response keys to form field names and merge into your client error state.

try {
  await api.submit(form);
} catch (e) {
  if (e.status === 422) setErrors(e.fieldErrors);
}

Common Mistakes

  • Relying only on client validation for security.
  • Showing errors without associating them with inputs accessibly.
  • Clearing errors inconsistently when user fixes a field.
  • Validating on every keystroke for simple required checks.

Key Takeaways

  • Validate on client for UX; always validate on server for security.
  • Use schema libraries for maintainable rules.
  • Surface errors accessibly with ARIA attributes.
  • Choose validation timing appropriate to the field.

Pro Tip

Share the same Zod schema between frontend and a Node backend (via a shared package) to avoid duplicated validation rules.