Concept of Controlled and Uncontrolled
Controlled vs. Uncontrolled Components in React: A Beginner's Guide
If you're new to React and working with forms, you've probably come across the terms controlled and uncontrolled components. They sound intimidating at first, but the idea is actually quite simple once you see it in action. Let's break it down.
What Is a Controlled Component?
In a controlled component, React state is the single source of truth for the input's value. Every time the user types something, an onChange handler fires, updates the state, and React re-renders the input with the new value. The DOM never decides what's in the box — React does.
Here's the classic example:
function App() {
const [fName, setFName] = useState('');
return (
<div className="container">
<h1>Hello {fName}</h1>
<input
name="fname"
value={fName}
onChange={(e) => setFName(e.target.value)}
type="text"
placeholder="What's your first name?"
/>
</div>
);
}The key line is value={fName}. By binding the input's value to a state variable, you're telling React: "You own this input. Whatever is in fName, that's what the input should show." The onChange handler then keeps the state in sync with what the user types.
Without value={fName}, the input would be uncontrolled — the DOM would manage its own value internally, and React wouldn't know what's in it unless you explicitly asked.
Why does this matter?
Because once React controls the value, you can:
Validate input in real-time (e.g., show an error while the user is still typing)
Conditionally disable a submit button based on the current value
Programmatically reset or pre-fill the form
Keep the UI and data always in sync
What Is an Uncontrolled Component?
Uncontrolled components work more like traditional HTML forms. The DOM manages the input's state internally, and you read the value only when you need it — typically on form submission — using a ref.
jsx
function App() {
const fNameRef = useRef(null);
function handleSubmit() {
console.log(fNameRef.current.value);
}
return (
<div className="container">
<input
name="fname"
ref={fNameRef}
type="text"
placeholder="What's your first name?"
/>
<button onClick={handleSubmit}>Submit</button>
</div>
);
}Notice there's no value prop and no onChange. React simply holds a reference to the DOM node, and you grab the value directly from it when needed.
Uncontrolled components are simpler to write for basic forms, and they're often the better choice when integrating with third-party, non-React libraries that manage their own DOM.
Controlled vs. Uncontrolled: Side-by-Side
Feature | Controlled | Uncontrolled |
|---|---|---|
Source of truth | React state | The DOM |
Data access | Via state variable | Via |
Updates |
| Manually, often on submit |
Real-time validation | Easy to implement | Harder; usually on submit |
Code verbosity | More boilerplate | Simpler for basic forms |
Which One Should You Use?
As a beginner, start with controlled components. They make your data flow explicit and predictable, which is the React way of thinking. You always know exactly what's in your form fields because it's right there in state.
Reach for uncontrolled components when:
Your form is simple and doesn't need real-time feedback
You're integrating with a library that controls the DOM itself (e.g., a rich-text editor or date picker)
You want to avoid re-renders on every keystroke for performance-sensitive scenarios
Quick Recap
Adding
value={state}to an input makes it controlled — React owns the value.Without
value, the input is uncontrolled — the DOM owns the value, and you useuseRefto read it.Controlled components are more powerful and predictable; uncontrolled are simpler for basic cases.
Also Explore these
Understanding this distinction will help you write cleaner React forms and debug them much faster. Once you're comfortable with this, explore topics like form libraries like React Hook Form which combine the simplicity of uncontrolled components with the power of controlled-style validation.
