The single source of truth
An HTML <input> stores its own value internally. In React we prefer that
value to live in the component's state: that way the state is the single source
of truth and the UI always reflects exactly what's stored.
A controlled input combines two things:
value={x}— the input displays the value from state.onChange={e => setX(e.target.value)}— every time the user types, we update the state withe.target.value(the input's current text).
function Echo() {
const [text, setText] = useState("");
return (
<div>
<input value={text} onChange={(e) => setText(e.target.value)} />
<p>You typed: {text}</p>
</div>
);
}
The flow is a closed loop: the user types → onChange fires →
setText changes the state → React re-renders → the input shows the
new value. The input never "decides" on its own: it only reflects the state.
Why it's useful
Since the value is in the state, you can read it, transform it, or validate it at any time: count characters, uppercase it, disable a button if it's empty... all without touching the DOM directly.
<input
value={name}
onChange={(e) => setName(e.target.value.toUpperCase())}
/>
Rule of thumb: if you set
value={...}you must also setonChange. WithoutonChange, the input would be "frozen" and the user couldn't type.