React Course
React
/
Intermediate

Controlled vs Uncontrolled

Definition

A Controlled component is a form element whose value is entirely driven by React state. An Uncontrolled component is a form element that maintains its own internal HTML state, accessed via a React `ref`.

Explain Like I'm New

Imagine a steering wheel. A 'Controlled' car is a modern self-driving car: React's computer (state) has its hands firmly on the wheel 100% of the time. It knows exactly where the wheel is at every millisecond. An 'Uncontrolled' car is a manual car: the driver (the DOM) holds the wheel. If React wants to know where the wheel is, it has to physically look at the driver (using a `ref`) and ask 'Hey, what's your current value?'.

Real World Example

If you want a login form where the 'Submit' button disables automatically until the password is 8 characters long, you MUST use a Controlled component, because React needs to know the password value at every single keystroke. If you just have a massive survey form and only care about the values when the user finally hits 'Submit', you can use Uncontrolled components for better performance.

Common Use Cases

  • Controlled: Instant form validation, disabling submit buttons, formatting text as the user types (like adding dashes to phone numbers)
  • Uncontrolled: Integrating with non-React libraries (like a jQuery datepicker), or massive forms where re-rendering on every keystroke causes lag

Interactive Example

import React, { useState, useRef } from 'react';

export default function FormExample() {
  // For the Controlled Input
  const [name, setName] = useState('');
  
  // For the Uncontrolled Input
  const ageRef = useRef(null);

  const handleSubmit = (e) => {
    e.preventDefault();
    // Controlled: We already know the value because it's in State!
    console.log("Controlled Name:", name);
    // Uncontrolled: We have to manually ask the DOM for the value.
    console.log("Uncontrolled Age:", ageRef.current.value);
  };

  return (
    <form onSubmit={handleSubmit} className="flex flex-col gap-4">
      <div>
        <h3>Controlled Input</h3>
        {/* React is the boss here. The value is locked to State. */}
        <input 
          type="text" 
          value={name}
          onChange={(e) => setName(e.target.value)}
          placeholder="Enter name (React tracks every keystroke!)"
          className="w-full p-2 border"
        />
        <p className="text-sm text-gray-500">Current state: {name}</p>
      </div>

      <div>
        <h3>Uncontrolled Input</h3>
        {/* The DOM is the boss here. We only use defaultValue to start it. */}
        <input 
          type="number" 
          ref={ageRef}
          defaultValue="18"
          placeholder="Enter age (React ignores keystrokes)"
          className="w-full p-2 border"
        />
      </div>

      <button type="submit" className="bg-blue-500 text-white p-2 rounded">
        Submit Form
      </button>
    </form>
  );
}

Interview Questions

basic

  • What is a Controlled Component?
  • How do you access the value of an Uncontrolled Component?

intermediate

  • Why does a Controlled input need both a `value` prop and an `onChange` handler?
  • What happens if you provide a `value` prop to an input without an `onChange` handler?

advanced

  • How does the `defaultValue` prop differ from the `value` prop?
  • Can a component switch between being controlled and uncontrolled during its lifecycle?

trick

  • Is it bad practice to use Uncontrolled components?

Flash Cards

Question

What happens if you provide a value without onChange?

Click to reveal answer
Answer

React will lock the input! Because React state is the 'single source of truth', if the `value` is hardcoded to `'hello'` and there's no `onChange` to update it, the user will be completely unable to type in the box. It becomes read-only.

Question

How does defaultValue differ from value?

Click to reveal answer
Answer

`value` is used for Controlled components to strictly define the current state. `defaultValue` is used for Uncontrolled components to set the initial HTML value on the first render, but lets the DOM handle the value from that point forward.

Question

Can a component switch between controlled and uncontrolled?

Click to reveal answer
Answer

No! If you try to change an input from having a `value` (controlled) to having `value={undefined}` (uncontrolled), React will throw a huge warning in the console. An input must remain controlled or uncontrolled for its entire lifespan.