Controlled Inputs

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.

4 min read Level 2/5 #react#forms#controlled
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 says
  • onChange={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.

ElementWhat you read on the eventWhat you set as value
<input> texte.target.valuevalue={state}
<input type="checkbox">e.target.checkedchecked={state}
<input type="radio">e.target.valuechecked={state === value}
<select>e.target.valuevalue={state}
<textarea>e.target.valuevalue={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 →