Course outline · 0% complete

0/28 lessons0%

Course overview →

Controlled inputs

lesson 6-1 · ~11 min · 16/28

Quiz

Warm-up from lesson 4-1: calling a state setter like setText("hi") does two things. Which two?

Controlled inputs

An <input> in plain HTML keeps its own text internally, the DOM owns the value. That clashes with React's model, where data lives in state and the UI is computed from it. Two owners of the truth means sync bugs, the exact disease from lesson 1-1.

A controlled input hands ownership to React:

function NameField() {
  const [name, setName] = useState("");
  return (
    <input
      value={name}
      onChange={e => setName(e.target.value)}
    />
  );
}

The cycle on every keystroke:

  1. The user types a character.
  2. onChange fires with the event e, and e.target.value is the input's proposed new text (the DOM event you know from Web Development Fundamentals).
  3. setName stores it and triggers a re-render.
  4. The re-render sets value={name}, so the input shows exactly what state says.

State is the single source of truth. The input displays state, never its own memory.

user types "a"onChange firessetName(e.target.value)state: name = "a"re-render:value={name}
The controlled-input cycle. A keystroke fires onChange, the setter stores the text in state, the re-render feeds state back into value, and the input shows exactly what state says.

Why bother with the loop?

Because step 3 is a hook point where your code decides what the input becomes. Validate, transform, or limit the text before storing it, and the input can never display anything invalid:

onChange={e => setCode(e.target.value.toUpperCase().slice(0, 6))}

Type abc1234xyz and the box shows ABC123. Try doing that reliably with an uncontrolled input and you end up fighting the DOM.

It also makes the rest of the app trivial: any component that needs the current text just reads the state variable. No document.querySelector("input").value anywhere.

Code exercise · javascript

The controlled-input loop without a browser. setCode plays the role of the onChange handler plus re-render: it transforms the proposed text and prints what the input would now display. Run it.

Quiz

Spot the bug: ```jsx const [email, setEmail] = useState(""); return <input value={email} />; ```