Controlled vs Uncontrolled Forms
In this page:
// Controlled: React state owns the value
<input value={state} onChange={e => setState(e.target.value)} />
// Uncontrolled: the DOM owns the value
const inputRef = useRef();
<input defaultValue="initial" ref={inputRef} />
// read with inputRef.current.value
What Makes an Input 'Controlled'
An input is controlled when its value prop is driven by React state, and onChange updates that state. This means React is the single source of truth for what's in the box at any moment — the displayed value always matches state exactly.
Example: What Makes an Input 'Controlled'
<!DOCTYPE html>
<html>
<head>
<script src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
</head>
<body>
<div id="root"></div>
<script type="text/babel">
function App() {
const [value, setValue] = React.useState("");
return <div><input value={value} onChange={e => setValue(e.target.value)} /><p>You typed: {value}</p></div>;
}
ReactDOM.createRoot(document.getElementById('root')).render(<App />);
</script>
</body>
</html>
What Makes an Input 'Uncontrolled'
An uncontrolled input manages its own internal value the normal HTML way, with no value prop from React. To read its current value, you attach a ref and access ref.current.value when you actually need it, like on form submit.
Example: What Makes an Input 'Uncontrolled'
<!DOCTYPE html>
<html>
<head>
<script src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
</head>
<body>
<div id="root"></div>
<script type="text/babel">
function App() {
const inputRef = React.useRef(null);
const handleClick = () => alert("Value: " + inputRef.current.value);
return <div><input ref={inputRef} defaultValue="Hello" /><button onClick={handleClick}>Read Value</button></div>;
}
ReactDOM.createRoot(document.getElementById('root')).render(<App />);
</script>
</body>
</html>
Choosing Between the Two Approaches
Controlled inputs are usually the default choice in React because they make validation, formatting, and conditional UI straightforward.
Uncontrolled inputs are useful for simple forms, file inputs (which can't be controlled), or when integrating a non-React widget.
Example: Choosing Between the Two Approaches
<!DOCTYPE html>
<html>
<head>
<script src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
</head>
<body>
<div id="root"></div>
<script type="text/babel">
function App() {
const [controlled, setControlled] = React.useState("");
const uncontrolledRef = React.useRef(null);
return (
<div>
<input value={controlled} onChange={e => setControlled(e.target.value)} placeholder="Controlled" />
<input ref={uncontrolledRef} defaultValue="" placeholder="Uncontrolled" />
<p>Controlled value: {controlled}</p>
</div>
);
}
ReactDOM.createRoot(document.getElementById('root')).render(<App />);
</script>
</body>
</html>
- Switching an input from controlled to uncontrolled (or back) during its lifetime, which React warns about.
- Using a ref to read an uncontrolled input's value on every render instead of only when needed (like on submit).
- Not providing defaultValue for an uncontrolled input, leaving it blank unexpectedly.
- A controlled input's value comes from React state and is updated via onChange.
- An uncontrolled input manages its own value internally; React reads it via a ref only when needed.
- Controlled inputs make validation and conditional logic easier since the value is always available in state.
- Uncontrolled inputs are simpler for very basic forms or integrating with non-React code.
No React-version restriction — refs and controlled inputs work identically across all supported React versions.
Chapter Quiz — Complete all 8 topics to unlock
0/8 topics done
Complete these topics first: