✍️ React Controlled vs Uncontrolled Components – A Complete Guide (2025)
🧲 Introduction – Why This Distinction Matters
React.js promotes a component-driven architecture, and nowhere is this more evident than in form handling. Knowing the difference between controlled and uncontrolled components helps developers choose the right strategy for managing user input, form state, and interactivity.
🎯 In this guide, you’ll learn:
- What controlled and uncontrolled components are
- Key differences in syntax and behavior
- Use cases and best practices
- When to use one over the other in real-world applications
🧩 What Are Controlled Components?
A controlled component is a form input element (like <input>
, <textarea>
, or <select>
) where the value is fully managed by React state.
✅ Controlled Input Example:
import { useState } from 'react';
function ControlledInput() {
const [value, setValue] = useState('');
return (
<input
type="text"
value={value}
onChange={(e) => setValue(e.target.value)}
/>
);
}
📌 React is the “single source of truth” for the input field.
🧩 What Are Uncontrolled Components?
An uncontrolled component uses the DOM itself to manage its own state. You access the input value using a ref, not via React state.
✅ Uncontrolled Input Example:
import { useRef } from 'react';
function UncontrolledInput() {
const inputRef = useRef();
const handleSubmit = () => {
alert(inputRef.current.value);
};
return (
<>
<input type="text" ref={inputRef} />
<button onClick={handleSubmit}>Submit</button>
</>
);
}
📌 React only accesses the value when needed, not on every change.
⚖️ Controlled vs Uncontrolled – Key Differences
Feature | Controlled Component | Uncontrolled Component |
---|---|---|
State managed by | React (useState ) | Browser DOM (ref ) |
Access method | value + onChange | ref.current.value |
Real-time validation | ✅ Easy | ❌ Harder |
Default values | value + state | defaultValue |
Performance | Slightly less efficient for large forms | More performant (no re-renders) |
Use case | Dynamic/interactive UIs | Simple, uncontrolled forms |
Debugging | Easier (all state in React) | Harder (value lives outside React) |
🧠 When to Use Controlled Components
✅ Ideal for:
- Real-time validation and formatting
- Conditional rendering based on input values
- Complex, dynamic forms (signup, checkout, dashboards)
✅ Example – Controlled Form with Validation:
const [email, setEmail] = useState('');
const isValid = email.includes('@');
return (
<>
<input
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
{!isValid && <p>Please enter a valid email.</p>}
</>
);
🧠 When to Use Uncontrolled Components
✅ Ideal for:
- Simple forms
- Performance-sensitive inputs (e.g., file uploads)
- Integrating with non-React libraries
✅ Example – File Upload Input:
function FileUploader() {
const fileInput = useRef();
const handleUpload = () => {
console.log(fileInput.current.files[0]);
};
return <input type="file" ref={fileInput} />;
}
📘 Hybrid Approach – Best of Both Worlds
Sometimes, you may want to mix controlled and uncontrolled patterns:
<input
type="text"
defaultValue="John Doe"
ref={inputRef}
onChange={(e) => console.log(e.target.value)}
/>
✅ Use defaultValue
for initial value
✅ Use ref
to access on submit
✅ Avoid assigning both value
and defaultValue
(React will warn you)
🧩 Forms Using Controlled Components
function SignupForm() {
const [form, setForm] = useState({ name: '', email: '' });
const handleChange = (e) => {
const { name, value } = e.target;
setForm((prev) => ({ ...prev, [name]: value }));
};
return (
<form>
<input name="name" value={form.name} onChange={handleChange} />
<input name="email" value={form.email} onChange={handleChange} />
</form>
);
}
✅ Best for multi-field or real-time validation forms
📌 Summary – Recap & Next Steps
React supports both controlled and uncontrolled components, each suited to specific use cases. Controlled components offer tight control and are best for interactive forms, while uncontrolled components are better for quick inputs or integrations with non-React tools.
🔍 Key Takeaways:
- Controlled components sync state with every user input
- Uncontrolled components store data in the DOM and access via
ref
- Controlled is better for validation, interactivity, and UI logic
- Uncontrolled is better for performance and simple use cases
⚙️ Real-World Relevance:
Choosing the right component type boosts maintainability, performance, and user experience in real-world React apps like form builders, CMS dashboards, and portals.
❓ FAQ Section
❓ Which is better: controlled or uncontrolled components?
✅ Controlled components are more robust and flexible. Use uncontrolled components only when needed for performance or simplicity.
❓ Can I switch between controlled and uncontrolled modes?
❌ Not dynamically. React may throw a warning. Stick with one pattern per input.
❓ Why is my controlled input not updating?
✅ Ensure the input uses both value
and onChange
. Missing onChange
means the field becomes read-only.
❓ Can I use both controlled and uncontrolled components in the same form?
✅ Yes. You can mix them but avoid managing the same field with both approaches.
❓ Do libraries like Formik or React Hook Form use controlled or uncontrolled components?
✅ Formik uses controlled components.
✅ React Hook Form uses uncontrolled components with refs for performance.
Share Now :