Stop 08 · ReactTopics · 10/20

Controlled Components

Part of the Frontend Developer Roadmap

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.

The jaadu mascot works a string puppet on a small stage with a wooden control bar.

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

Keyboard
<input>
PhoneInput
React

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

tsx
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

~15 min

Quick check

You write <input value={name} /> with no onChange. What happens when the user types?

Go deeper

  1. 1Convert an uncontrolled input (using a ref) into a controlled one.
  2. 2Notice how controlled inputs let you validate/transform input on every keystroke.
  3. 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.

Download
InsideEdge