📘 ReactJS

Controlled vs Uncontrolled Components

Forms are one of the clearest places to understand the difference between React state and the DOM itself. In a controlled component, React state is the source of truth for the input value. In an uncontrolled component, the DOM keeps the current value and React reads it when required.

S

Site Administrator

📅 Sep 28, 2026 🕒 4 min read 👁 24 views
☆ Save 𝕏 in f ✆
Controlled vs Uncontrolled Components

Forms are one of the clearest places to understand the difference between React state and the DOM itself. In a controlled component, React state is the source of truth for the input value. In an uncontrolled component, the DOM keeps the current value and React reads it when required.

Controlled component

A controlled input receives its value from React state and reports changes through an event handler. React therefore owns the current value.

function LoginForm() {
  const [email, setEmail] = useState("");

  return (
    <input
      value={email}
      onChange={event => setEmail(event.target.value)}
    />
  );
}

Controlled input flow

flowchart TD
A[User types] --> B[onChange]
B --> C[setState]
C --> D[Component renders]
D --> E[value comes from state]
E --> F[Input displays value]

Why controlled components are useful

Because React owns the value, validation, formatting, conditional UI, enabling and disabling buttons, and displaying errors can all use the same state. This is especially useful for complex business forms.

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

<button disabled={!isValid}>
  Continue
</button>

Uncontrolled component

In an uncontrolled component, the browser DOM maintains the input value. React can access the current value through a ref when it needs to read it.

function SearchForm() {
  const inputRef = useRef(null);

  function handleSubmit(event) {
    event.preventDefault();
    console.log(inputRef.current.value);
  }

  return (
    <form onSubmit={handleSubmit}>
      <input ref={inputRef} />
      <button>Search</button>
    </form>
  );
}

Default values

For uncontrolled inputs, defaultValue can provide the initial value without making React responsible for every subsequent change.

<input defaultValue="Initial value" />

Controlled vs uncontrolled

AreaControlledUncontrolled
Source of truthReact stateDOM
Current valueState variableRef or form APIs
ValidationEasy to coordinate with stateUsually performed when reading/submitting
Every keystrokeCan update React stateDoes not require React state update
Complex dynamic formsOften convenientCan reduce state management

When controlled is a good fit

  • Live validation is required.
  • Input affects other parts of the UI.
  • Formatting must happen as the user types.
  • Submit availability depends on current values.
  • Complex business rules depend on form state.

When uncontrolled is a good fit

  • The form is simple.
  • You mainly need values at submit time.
  • You want to avoid state for every field.
  • You are integrating with code or libraries that work directly with DOM inputs.

File inputs

File inputs are a special case because browsers control the selected file value for security reasons. React applications commonly use a ref or the form event to access selected files rather than trying to control the file path as normal state.

function Upload() {
  function handleChange(event) {
    const file = event.target.files?.[0];
    console.log(file);
  }

  return <input type="file" onChange={handleChange} />;
}

Avoid mixing controlled and uncontrolled behavior

An input should generally have a consistent ownership model. Switching an input between controlled and uncontrolled modes can produce warnings and confusing behavior. Decide whether React or the DOM is the source of truth.

Validation example

function RegistrationForm() {
  const [email, setEmail] = useState("");
  const [error, setError] = useState("");

  function handleSubmit(event) {
    event.preventDefault();

    if (!email.includes("@")) {
      setError("Enter a valid email");
      return;
    }

    setError("");
    // submit
  }

  return (
    <form onSubmit={handleSubmit}>
      <input
        value={email}
        onChange={event => setEmail(event.target.value)}
      />
      {error && <p>{error}</p>}
      <button type="submit">Register</button>
    </form>
  );
}

Common mistakes

  • Using value without an onChange handler and expecting the input to remain editable.
  • Switching between undefined and a defined value unexpectedly.
  • Using refs for complex state that should be visible in the UI.
  • Assuming uncontrolled means React cannot access the value.

Interview questions

  • What is a controlled component?
  • What is an uncontrolled component?
  • When would you use useRef for a form?
  • What is the difference between value and defaultValue?
  • Why are file inputs commonly handled differently?

Key takeaways

  • Controlled means React state owns the value.
  • Uncontrolled means the DOM owns the value.
  • Controlled forms are useful for rich validation and UI behavior.
  • Uncontrolled forms can be simple and efficient for straightforward scenarios.

Comments & Ratings (0)

Log in or create a student account to comment and rate this article.

Be the first to comment on this article.

Never miss a new post 📬

Get an email whenever a new article, project, cheatsheet or video drops.

✅

ℹ️