What is the difference between controlled and uncontrolled components in React?
In a controlled component, React state holds the input's value and every change goes through an onChange handler. In an uncontrolled component, the browser DOM keeps the value and you read it when needed, for example with a ref or from the form data on submit.
Explain it simply
Think of filling an exam form at the college office. In one office, a clerk checks every line as you write it and tells you immediately if your roll number has the wrong format. In another office, you fill the whole form yourself and the clerk reads it only when you submit.
A controlled input is the first office. React state is the single source of truth. The input shows whatever is in state, and every keystroke calls a handler that updates state. Because you see every change, you can validate, format or block input as the user types.
An uncontrolled input is the second office. The browser keeps the value inside the DOM element, as it normally does in plain HTML. React does not track each keystroke. You read the value when you need it, usually on submit.
Example
// Controlled: React state owns the value
function PhoneInput() {
const [phone, setPhone] = useState("");
return (
<input
value={phone}
onChange={(e) => setPhone(e.target.value.replace(/\D/g, "").slice(0, 10))}
placeholder="10-digit mobile number"
/>
);
}
// Uncontrolled: the DOM owns the value, read it on submit
function FeedbackForm() {
function handleSubmit(e) {
e.preventDefault();
const data = new FormData(e.currentTarget);
console.log(data.get("feedback"));
}
return (
<form onSubmit={handleSubmit}>
<textarea name="feedback" defaultValue="" />
<button type="submit">Send</button>
</form>
);
}The phone input strips non-digits and limits length as you type, which needs a controlled input. The feedback form only needs the value at the end, so uncontrolled is simpler.
How it works
- A controlled input uses
value(orcheckedfor checkboxes) plusonChange. If you setvaluewithoutonChange, the input becomes read-only and React warns you. - An uncontrolled input uses
defaultValue(ordefaultChecked) to set only the starting value. After that, the DOM manages it. You read it with a ref (useRef) or fromFormData. - In React 19, a
<form>can take a function as itsaction. React calls it with the form'sFormDataon submit, which makes uncontrolled forms convenient for simple cases.
Real-world use
- Controlled: live validation, input masks for phone or PAN-style codes, enabling the submit button only when fields are valid, search boxes that filter as you type.
- Uncontrolled: simple contact or feedback forms, file inputs (
<input type="file">is always uncontrolled because its value cannot be set by code), and integrating non-React widgets. - Form libraries often use uncontrolled inputs with refs internally to avoid re-rendering on every keystroke in very large forms.
Common mistakes
- Switching between controlled and uncontrolled, for example starting with
value={undefined}and later passing a string. React warns about this. Initialise state with""instead ofundefined. - Using both
valueanddefaultValueon the same input. - Setting
valuebut forgettingonChange, so the user cannot type. - Assuming controlled is always better. It re-renders on every keystroke, which is usually fine but unnecessary for simple forms.
What to say in the interview
"In a controlled component the input's value comes from React state and every change goes through onChange, so React is the single source of truth. That makes live validation and formatting easy. In an uncontrolled component the DOM keeps the value, I set only a defaultValue, and I read the value with a ref or FormData when needed, usually on submit. I use controlled inputs when the UI reacts to each keystroke, and uncontrolled ones for simple forms and file inputs."
Follow-up questions
- Why is a file input always uncontrolled?
- What warning do you get when an input switches from uncontrolled to controlled, and why?
- How do form actions in React 19 change the way you handle simple forms?