Lesson 37 +10 XP

Controlled vs Uncontrolled Forms

Controlled vs Uncontrolled Forms

Form elements (<input>, <textarea>, <select>) maintain their own internal DOM state by default in traditional HTML. In React, there are two distinct ways to handle form input state: Controlled Components and Uncontrolled Components.

Controlled Components (Recommended)

In a Controlled Component, React component state is the single source of truth for the input's value. Input values are bound to state via value={state} and updated on user typing via onChange={handler}.

import { useState } from 'react';

function ControlledForm() {
  const [email, setEmail] = useState('');

  const handleSubmit = (e) => {
    e.preventDefault();
    console.log("Submitted email:", email);
  };

  return (
    <form onSubmit={handleSubmit}>
      <label>Email:</label>
      <input 
        type="email" 
        value={email} // Value driven by React state
        onChange={(e) => setEmail(e.target.value)} // State updated on keystroke
      />
      <p>Current input length: {email.length} characters</p>
      <button type="submit">Submit</button>
    </form>
  );
}

Benefits of Controlled Components

  • Instant field validation on every keystroke.
  • Dynamic input formatting (e.g. credit card spacing, phone number masks).
  • Disabling submit buttons based on real-time field validation.

Uncontrolled Components

In an Uncontrolled Component, input data is handled directly by the browser's DOM. You query the DOM element's value when needed using a useRef.

import { useRef } from 'react';

function UncontrolledForm() {
  const emailRef = useRef(null);

  const handleSubmit = (e) => {
    e.preventDefault();
    // Read input value directly from DOM element ref!
    console.log("Submitted email:", emailRef.current.value);
  };

  return (
    <form onSubmit={handleSubmit}>
      <label>Email:</label>
      <input ref={emailRef} type="email" defaultValue="user@example.com" />
      <button type="submit">Submit</button>
    </form>
  );
}

Summary & TL;DR

  • Controlled Components: Input value is bound to React state (value + onChange). React is single source of truth.
  • Uncontrolled Components: Input value is managed by the DOM; values are pulled using useRef.
  • Controlled components are preferred for real-time validation and dynamic form logic.