DEV Community

Cover image for Master React Forms with Controlled and Uncontrolled Components
Miguel Miranda
Miguel Miranda

Posted on

Master React Forms with Controlled and Uncontrolled Components

Why Should You Understand This?

When you start working with forms in React, sooner or later you face this question:

Should I use a controlled or uncontrolled component?

It might seem like a minor technical decision, but understanding this difference impacts:

  • How you manage form state
  • How easily you can validate user input
  • How well your application scales

Let's explore why this matters, how each type works, and when to choose one over the other.


The Problemđź’Ą

Suppose you're building a contact form. Everything works fine until you need to:

  • Validate the input as the user types
  • Reset the fields from your code
  • Submit the form with complex logic

That's when the key difference appears:

Do you want React to control the input or not?


🔍 Controlled Components

A controlled component is one whose value is managed by React's state.

Every time the user types, an onChange event is triggered, updating the state and causing React to re-render with the new value.

Example:

import { useState } from "react";

function FormControlled() {
  const [name, setName] = useState("");

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

  return (
    <form onSubmit={handleSubmit}>
      <input
        type="text"
        value={name}
        onChange={(e) => setName(e.target.value)}
        placeholder="Enter your name"
      />
      <button type="submit">Submit</button>
    </form>
  );
}
Enter fullscreen mode Exit fullscreen mode

🔑 Key Points

  • âś… React always knows what's in the input
  • âś… Ideal for real-time validation and complex forms
  • ❌ More code, potentially slower with heavy inputs (e.g., large <textarea>)

⚡ Uncontrolled Components

An uncontrolled component uses a reference (ref) to access its value. React does not manage the value — the DOM handles it directly.

Why?

Libraries like Stripe Elements, TinyMCE, or even an embedded YouTube video player are not designed for React. They:

  • Render directly to the DOM (outside React's control)
  • Expect the DOM to be ready before they mount
  • Use their own internal systems to listen to events and update their content

If you try to control these kinds of inputs with React’s value and onChange, you may run into conflicts — or it may simply not work at all.

Example:

import { useRef } from "react";

function FormUncontrolled() {
  const nameRef = useRef(null);

  const handleSubmit = (e) => {
    e.preventDefault();
    console.log("Name:", nameRef.current.value);
  };

  return (
    <form onSubmit={handleSubmit}>
      <input type="text" ref={nameRef} placeholder="Enter your name" />
      <button type="submit">Submit</button>
    </form>
  );
}
Enter fullscreen mode Exit fullscreen mode

🔑 Key Points

  • âś… Less code and faster for simple inputs
  • âś… Useful for integrating external libraries (e.g., DOM APIs or legacy forms)
  • ❌ Harder to validate or control in real time

đź§Ş Real-World Applications

Suppose you're building a login form with real-time validation. Controlled components are perfect here:

<input
  value={email}
  onChange={(e) => {
    setEmail(e.target.value);
    setError(validateEmail(e.target.value));
  }}
/>
Enter fullscreen mode Exit fullscreen mode

But if you're integrating something like Stripe Elements, where the input is rendered by their API, you’ll need to use an uncontrolled component with ref.


📸 Visual Illustration

Controlled components follow the flow React → state → view, while uncontrolled components go DOM → access via ref


⚔️ Side-by-Side Comparison

Aspect Controlled Uncontrolled
Who manages the value? React (useState) DOM (ref)
Real-time validation ✅ Easy ❌ Harder
Library integration ❌ Sometimes tricky ✅ More straightforward
More code required ✅ Yes ❌ No
Performance ❌ Can be slower ✅ Faster for simple inputs

âś… When to Use Each

Scenario Best Option
Forms with validation Controlled
Simple forms or performance concerns Uncontrolled
Integration with external libraries Uncontrolled
Dynamic form logic or state syncing Controlled

đź§  Conclusion

This isn't just React trivia...
It’s key to building forms that scale, are predictable, and provide a great user experience.

đź’ˇ General Rule:

If you need validation, dynamic updates, or syncing with state → controlled.

If you need simplicity or work with external tools → uncontrolled.


👋 If you found this article interesting or want to get in touch, I’m active on X @mirchezz

Top comments (1)

Collapse
 
codedbysejal profile image
codedbysejal👩‍💻

It's really helpful breakdown of controlled vs uncontrolled components cleared up a lot of confusion for me...Thanks for the clear examples and explanations🔥