In short
Sometimes you need to respond to every keystroke: live search, a character counter, formatting a phone number. Controlled inputs put React fully in charge of what's in the box.
Form inputs whose value is driven entirely by React state (`value` + `onChange`), making React the 'single source of truth' for the input's value.

Think of it like this
A kathputli puppet show
The puppet never moves on its own. Every step happens because the puppeteer pulls a string. A controlled input is that puppet: it shows only what state says, and it changes only when your code updates state.
Watch it happen
Why the letter never appears
key: a
1/5The box shows 98. You type the letter a.
The big ideas
What you need to know
value comes from state
Set value={text} on the input. It now always shows exactly what's in state.
onChange updates state
Each keystroke calls onChange, you call setText(e.target.value), and React re-renders with the new value.
Uncontrolled is fine too
If you only need the values on submit, let the DOM hold them and read FormData. Less code.
Easy to clean up input
Since you set the value, you can trim it, uppercase it or block characters before saving.
See it in code
Walk through the code
1import { useState } from "react";2 3export default function PhoneInput() {4 const [phone, setPhone] = useState("");5 6 return (7 <label>8 Mobile9 <input10 value={phone}11 onChange={(e) => setPhone(e.target.value.replace(/\D/g, "").slice(0, 10))}12 />13 <small>{phone.length}/10</small>14 </label>15 );16}1/4State holds the phone number. It starts as an empty string, not undefined.
Letters never appear, because the handler strips anything that isn't a digit before it reaches state. That kind of control is the main reason to use controlled inputs.
Save yourself the pain
Common mistakes
Oops
Setting value without onChange, then wondering why you can't type.
Do this instead
A value with no onChange makes the input read-only. Add onChange, or use defaultValue for an uncontrolled field.
Oops
Starting state as undefined and later switching it to a string.
Do this instead
Start with an empty string. Going from undefined to a value makes React warn about switching from uncontrolled to controlled.
Your mission
Live character counter
Quick check
You write <input value={name} /> with no onChange. What happens when the user types?
Go deeper
- 1Convert an uncontrolled input (using a ref) into a controlled one.
- 2Notice how controlled inputs let you validate/transform input on every keystroke.
- 3Learn when uncontrolled inputs (with refs) are actually the simpler choice.
More topics at this stop
Stuck on this topic? Ask an Insider
Get 1:1 guidance from people who've walked this exact path — on the InsideEdge app.