The Input's Value Lives in React State
Controlled Inputs
A controlled input has `value` set from state and `onChange` wired to a setter. React is the single source of truth.
What you'll learn
- Build a controlled text input
- Read and validate input values as the user types
- Recognize uncontrolled inputs (and when they're useful)
A controlled input is one whose value React holds in state.
The DOM input shows whatever React tells it to; the user’s typing
flows into state via an onChange handler.
The Pattern
function NameField() {
const [name, setName] = useState("");
return (
<input
value={name}
onChange={e => setName(e.target.value)}
/>
);
} Two parts:
value={name}— display whatever state saysonChange={e => setName(e.target.value)}— store every keystroke
That’s the whole pattern. Memorize it.
Why Bother?
Once the value is in state, you can:
- Validate as the user types — disable a button, show an error
- Transform — uppercase, mask, strip whitespace
- Display the same value elsewhere — derived UI updates with it
- Reset with a single
setName("")
function EmailField() {
const [email, setEmail] = useState("");
const valid = /^\S+@\S+\.\S+$/.test(email);
return (
<div>
<input
type="email"
value={email}
onChange={e => setEmail(e.target.value.trim())}
/>
{!valid && email && <p>That doesn't look like an email.</p>}
</div>
);
} Each Input Type
The pattern is the same — just different DOM properties.
| Element | What you read on the event | What you set as value |
|---|---|---|
<input> text | e.target.value | value={state} |
<input type="checkbox"> | e.target.checked | checked={state} |
<input type="radio"> | e.target.value | checked={state === value} |
<select> | e.target.value | value={state} |
<textarea> | e.target.value | value={state} |
A checkbox example:
const [agreed, setAgreed] = useState(false);
<label>
<input
type="checkbox"
checked={agreed}
onChange={e => setAgreed(e.target.checked)}
/>
I agree
</label> Uncontrolled Inputs
You CAN skip state and read the value at submit time via a ref — that’s an uncontrolled input. It works, and it’s lighter (no re-render per keystroke). But you lose live validation, easy reset, and instant-feedback UX. We’ll come back to refs and uncontrolled inputs later.
Up Next
A real form has many inputs. Here’s the clean way to wire them up.
Controlled Forms →