What is the difference between controlled and uncontrolled components in React?

Controlled components store form input values in React state; uncontrolled components let the DOM manage the value and read it via a ref.

React

Overview

In a **controlled** component, React is the "single source of truth" for the input's value - you store it in state and pass it back to the input via `value`. In an **uncontrolled** component, the DOM manages the value internally and you read it via a `ref` when needed.

Key Points

  • •Controlled: `value` + `onChange` both wired to React state. React owns the value.
  • •Uncontrolled: no `value` prop. Use a `ref` to read the input's current value on demand.
  • •Use `defaultValue` (not `value`) to set an initial value in uncontrolled inputs.
  • •Controlled components enable real-time validation, conditional enabling, and instant feedback.
  • •Uncontrolled components are simpler and closer to plain HTML, but harder to synchronise.
  • •File inputs are always uncontrolled - the browser manages the file list.

Examples

Controlled input (React owns the value)

tsx
import { useState } from 'react';

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

  const isValid = email.includes('@');

  return (
    <form onSubmit={e => { e.preventDefault(); console.log(email); }}>
      <input
        type="email"
        value={email}                          // React drives the value
        onChange={e => setEmail(e.target.value)} // React updates on every keystroke
        style={{ borderColor: isValid ? 'green' : 'red' }} // real-time validation
      />
      <button disabled={!isValid}>Submit</button>
    </form>
  );
}

Uncontrolled input (DOM owns the value)

tsx
import { useRef } from 'react';

function UncontrolledForm() {
  const emailRef = useRef<HTMLInputElement>(null);

  const handleSubmit = (e: React.FormEvent) => {
    e.preventDefault();
    console.log(emailRef.current?.value); // read value on submit only
  };

  return (
    <form onSubmit={handleSubmit}>
      <input type="email" defaultValue="" ref={emailRef} />
      <button type="submit">Submit</button>
    </form>
  );
}

When to choose each

text
Controlled         | Uncontrolled
-------------------|------------------
Real-time validation| Simple read-on-submit
Dependent fields   | One-time forms
Format as you type | File inputs
Derived UI state   | Quick prototypes

Pro Tip

Libraries like React Hook Form and Formik work primarily with uncontrolled inputs (using refs) for performance - they avoid re-rendering the whole form on every keystroke. For most application forms, controlled inputs are the idiomatic React approach.