In a controlled component, form data is held in React state and updated via event handlers; in an uncontrolled component, the DOM itself keeps track of the form data, and React reads it only when needed (e.g. via a ref).
This distinction matters most for form inputs — text fields, checkboxes, selects — and reflects two different philosophies for who "owns" the current value.
const [value, setValue] = useState('');
<input
value={'{'}value{'}'}
onChange={'{'}e => setValue(e.target.value){'}'}
/>
The input's value is always driven by React state — every keystroke updates state via onChange, and the input displays whatever that state currently holds. This gives React full visibility and control over the value at every moment, making validation, formatting, or conditionally disabling submission straightforward.
const inputRef = useRef(null);
<input ref={'{'}inputRef{'}'} defaultValue="" />
// read it later:
inputRef.current.value
The DOM manages the input's value internally, the way a plain HTML form normally would. React only reaches in to read the current value when it actually needs it (like on form submit), using a ref rather than state.
Controlled components are the more common recommendation in React, since they keep the UI and state in sync and make validation easier. Uncontrolled components can be simpler for very basic forms, or when integrating with non-React code that expects to manage the DOM itself.
Last reviewed: September 2026