Controlled vs. Uncontrolled Components in React
Controlled and Uncontrolled Components
~10 Min. Lesezeit Zuletzt aktualisiert am August 8, 2026
Welcome to Phase 3: we're now going to build a real form – a review form for our products. Before we start, you need to understand a fundamental distinction: "controlled" versus "uncontrolled" form fields.
Controlled fields: the React-typical way
You already saw controlled fields in chapter 9 (our search field), without us naming it: the VALUE of the field comes from React state (value={{...}}), and EVERY change flows immediately back into state (onChange={{...}}). React thereby "controls" the field value completely – the DOM element itself practically has no state of its own anymore.
function ControlledField() {
const [value, setValue] = useState('');
return (
<input
value={value}
onChange={(event) => setValue(event.target.value)}
/>
);
}Uncontrolled fields: the classic HTML way
With uncontrolled fields, you let the DOM element itself manage its value – exactly like in classic HTML. You only read the current value when needed, usually via a ref (see chapter 9):
function UncontrolledField() {
const inputRef = useRef(null);
function handleSubmit(event) {
event.preventDefault();
console.log('Value on submit:', inputRef.current.value);
}
return (
<form onSubmit={handleSubmit}>
<input ref={inputRef} defaultValue="" />
<button type="submit">Submit</button>
</form>
);
}defaultValue instead of value matters here: defaultValue only sets the INITIAL value, then leaves control to the DOM – unlike value, which React enforces on EVERY render.
Direct comparison: which pattern, when?
| Situation | Recommended pattern |
|---|---|
| Value needs to be known as React state AT ALL TIMES, e.g. for live validation, live filtering, or live preview | Controlled (with value + onChange) |
| Value is only needed ONCE, on submit, e.g. simple forms with no live feedback | Uncontrolled (with ref + defaultValue) – slightly less code, but less control |
File uploads (<input type="file">) | MUST be uncontrolled – for security reasons, a file field's value cannot be set via JavaScript in the browser |
Achtung: An <input> must not switch between controlled and uncontrolled – React warns in the console with "A component is changing an uncontrolled input to be controlled" if value starts out undefined and later gets a real value. Always initialize controlled fields with a real starting value, e.g. useState('') instead of useState().
Tipp: In practice, and throughout the rest of this tutorial, you'll mostly see controlled fields – they're the more React-typical, predictable approach. Uncontrolled fields are good to know about (indispensable for file uploads, for instance), but rarely the first choice.