React Interview Question: Controlled vs Uncontrolled Components
Short answer: a controlled input's value comes from React state and changes through onChange. An uncontrolled input keeps its own value in the DOM; you read it when needed (via a ref or FormData).
Controlled
function Search() {
const [query, setQuery] = useState('');
return (
<>
<input value={query} onChange={(e) => setQuery(e.target.value)} />
<p>{query.length}/50 characters</p>
</>
);
}
- React state is the single source of truth.
- Easy to validate as the user types, transform input, or enable/disable buttons.
- Re-renders on every keystroke (usually fine).
Uncontrolled
function Signup() {
async function submit(formData) {
await api.signup(Object.fromEntries(formData));
}
return (
<form action={submit}>
<input name="email" type="email" defaultValue="" required />
<button>Sign up</button>
</form>
);
}
- Less code, fewer re-renders.
- Works naturally with React 19 form actions and progressive enhancement.
- Harder to react to every change (live validation, dependent fields).
Common bug
<input value={name} /> // no onChange: the field becomes read-only
<input value={user.name ?? undefined} onChange={...} /> // switching between undefined and a value
// triggers the "uncontrolled to controlled" warning
Use defaultValue for uncontrolled inputs, and make sure controlled inputs always have a defined value (use '' instead of undefined).
How to choose
Simple forms submitted as a whole: uncontrolled with actions or a form library. Inputs that drive other UI as you type: controlled.
Was this article helpful?
Comments
No comments yet. Have a question or a tip? Be the first to share it.