Uncontrolled vs Controlled React Components

Published: (February 3, 2026 at 10:50 PM EST)
2 min read
Source: Dev.to

Source: Dev.to

React offers developers various methods to manage and handle components within applications. Two prevalent approaches are uncontrolled and controlled components. While both serve the purpose of managing user inputs and interactions, they differ significantly in implementation and use cases.

Uncontrolled Components

Uncontrolled components rely on the DOM to hold their state. React does not directly control the values; instead, it reads them when needed (e.g., on form submission).

Advantages

  • DOM‑driven: Form data is managed by the DOM itself.
  • Integration with non‑React code: Easier to work with external libraries or legacy code where the source of truth remains in the DOM.
  • Simplified implementation: Fewer state handlers are required, which can be handy for large forms.
  • Potential performance benefit: React isn’t involved in every input change, reducing re‑render overhead.

Disadvantages

  • Limited control: Harder to enforce validation rules or synchronize with other React features (e.g., Context, PropTypes).
  • Testing challenges: Since state lives in the DOM, simulating interactions and asserting outcomes can be more complex.

Example

import React, { useRef } from "react";

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

  function handleSubmit(event) {
    event.preventDefault();
    console.log("Submitted value:", inputRef.current.value);
  }

  return (
    
      
        Name:
        
      
      Submit
    
  );
}

export default UncontrolledForm;

In this example, the input’s value is managed by the DOM (defaultValue). React reads the current value only when the form is submitted.

Controlled Components

Controlled components keep their state inside React. The component’s rendered output always reflects the current state, and user interactions update that state via event handlers.

Advantages

  • Full control: React can enforce validation, integrate with other features, and guarantee predictable behavior.
  • Improved testing: State is explicit, making it straightforward to simulate changes and assert results.
  • Centralized state management: All form data lives in React state, enabling easy sharing and manipulation.
  • Clear event handling: onChange (or similar) handlers keep the UI in sync with state.

Disadvantages

  • Increased complexity: Requires explicit state handling for each input, which can become verbose for large forms.
  • Potential performance overhead: Frequent state updates trigger re‑renders, which may affect performance in very large or highly interactive forms.

Example

import React, { useState } from "react";

function ControlledForm() {
  const [name, setName] = useState("John Doe");

  function handleChange(event) {
    setName(event.target.value);
  }

  function handleSubmit(event) {
    event.preventDefault();
    console.log("Submitted value:", name);
  }

  return (
    
      
        Name:
        
      
      Submit
    
  );
}

export default ControlledForm;

Here, the input’s value is bound to React state (name). The onChange handler updates that state, ensuring the UI always reflects the current value.

Back to Blog

Related posts

Read more »