React - Forms & Controlled Components

Controlled Inputs

In a controlled component, form values are driven by React state.

Try it: Name Form

View source
const { useState } = React;
function NameForm(){
  const [name, setName] = useState('');
  return (
    <form onSubmit={e => { e.preventDefault(); alert(`Hello ${name}`); }}>
      <label>
        Name: <input value={name} onChange={e => setName(e.target.value)} />
      </label>
      <button type="submit" style={{marginLeft:8}}>Greet</button>
    </form>
  );
}
ReactDOM.createRoot(document.getElementById('try-forms')).render(<NameForm />);

Syntax primer (for newcomers)

  • Controlled input: <input value={name} onChange={e => setName(e.target.value)} />
  • For checkboxes use checked and e.target.checked.
  • Prevent default form submit with e.preventDefault().

More examples

Controlled select and checkbox:

View source
const { useState } = React;
function PreferenceForm(){
  const [lang, setLang] = useState('js');
  const [agree, setAgree] = useState(false);
  return (
    <form onSubmit={e => { e.preventDefault(); alert(`${lang} / ${agree}`); }}>
      <label>Language: <select value={lang} onChange={e => setLang(e.target.value)}>
        <option value="js">JavaScript</option>
        <option value="ts">TypeScript</option>
      </select></label>
      <label style={{marginLeft:8}}>
        <input type="checkbox" checked={agree} onChange={e => setAgree(e.target.checked)} /> Agree
      </label>
      <button style={{marginLeft:8}}>Save</button>
    </form>
  );
}
ReactDOM.createRoot(document.getElementById('try-forms-2')).render(<PreferenceForm />);

Vocabulary

  • Controlled component: Form input whose value is driven by React state.
  • Uncontrolled component: Form input that manages its own state in the DOM.

Common pitfalls

  • Mixing controlled and uncontrolled inputs causes warnings; once you add value, keep it controlled.
  • Checkboxes use checked and onChange with e.target.checked—not value.
  • For non-submit buttons inside forms, set type="button" to avoid accidental submit.

Exercises

  1. Add length validation (min 3 chars) and show an inline error message while typing.
  2. Add a required agreement checkbox; disable the submit button until it’s checked.
  3. Split the name into first and last fields and show a computed full name preview.