Skip to content

Lesson 7 — Typed controlled forms and validation

Objective

Build a study-session form with explicit draft state, validation, and accessible feedback.

Prerequisites

Lesson 6 — React Router and lazy routes. You should be comfortable with controlled inputs and event handlers.

Mental Model

Controlled inputs make React state the source of truth. Validation is a domain decision; browser constraints can improve UX but do not replace trusted-boundary validation.

Concept

A controlled form keeps every input value in state. Draft state stays as strings or raw input values until the user submits. At submission, the code validates the values and converts them into a domain object. Errors are announced and associated with fields so assistive technology can find them.

Example

function SessionForm({ onSubmit }: { onSubmit: (s: Session) => void }) {
  const [topic, setTopic] = useState('');
  const [minutes, setMinutes] = useState('');

  const handleSubmit = (e: FormEvent) => {
    e.preventDefault();
    const parsed = Number(minutes);
    if (!Number.isFinite(parsed) || parsed < 1 || parsed > 240) return;
    onSubmit({ topic, minutes: parsed });
  };

  return (
    <form onSubmit={handleSubmit}>
      <label htmlFor="topic">Topic</label>
      <input id="topic" value={topic} onChange={(e) => setTopic(e.target.value)} />
      {/* ... */}
    </form>
  );
}

Real-World Usage

Checkout flows, settings panels, scheduling tools, and any form where user input must be parsed, validated, and reported clearly.

Common Mistakes

  • Converting input strings to numbers before the user finishes typing.
  • Relying only on HTML5 validation for security or business rules.
  • Announcing errors visually but not programmatically.

Mini Lab

Task

Capture topic, integer minutes, and notes. Require 1–240 minutes and meaningful notes. Dispatch a valid session, reset successful drafts, and preserve invalid input for correction.

Constraints

  • Test submission by accessible roles.
  • Check labels, focus behavior, status announcements, whitespace, decimals, and boundary values.

Expected Result

Invalid submissions are blocked with clear, per-field feedback. Valid submissions dispatch a Session object and reset the form without losing the user's place.

Hints

Keep draft strings as strings until validation so partially entered numbers remain representable. Convert into a domain object only after checks pass.

Knowledge Check

  • Controlled versus uncontrolled forms?
  • When should validation run?
  • How do you prevent duplicate submissions for async saves?

Challenge

A stakeholder wants real-time validation after every keystroke. What are the risks, and how would you balance feedback timing with accessibility?

Summary

Controlled forms own input state. Validate at the domain boundary and communicate errors accessibly.

What Comes Next

Lesson 8 — Fetching and async state