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>
);
}
🔑 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>
);
}
🔑 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));
}}
/>
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
⚔️ 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)
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🔥