Skip to content

React Tutorial Forms and Validation

Select, Checkbox and Radio Inputs in React

Lesson 74 of 156 1 min read By Deepak Paswan Updated Oct 10, 2026

Runnable lesson · press Try it on the examples to edit and run them here.

Different inputs store their value in different ways. This lesson gives you a reliable recipe for each.

Text, textarea, select: value

App.jsx
JSX
function App() {
  const [country, setCountry] = React.useState("uk");
  const [message, setMessage] = React.useState("");

  return (
    <form onSubmit={(e) => e.preventDefault()}>
      <label>
        Country
        <select aria-label="Country" value={country} onChange={(e) => setCountry(e.target.value)}>
          <option value="uk">United Kingdom</option>
          <option value="us">United States</option>
          <option value="in">India</option>
        </select>
      </label>
      <label>
        Message
        <textarea aria-label="Message" value={message} onChange={(e) => setMessage(e.target.value)} />
      </label>
      <p>Country: {country}</p>
      <p>Message: {message}</p>
    </form>
  );
}

Notes:

  • On <select>, set value on the select, not selected on options.
  • A <textarea> takes its text from the value prop (in HTML it takes children).

One checkbox: checked

App.jsx
JSX
function App() {
  const [dark, setDark] = React.useState(false);
  return (
    <div>
      <label>
        <input type="checkbox" checked={dark} onChange={(e) => setDark(e.target.checked)} />
        Dark mode
      </label>
      <p>Dark mode is {dark ? "on" : "off"}</p>
    </div>
  );
}

A group of checkboxes: an array

When several boxes make one answer, store the chosen values in an array and add or remove on change:

App.jsx
JSX
function App() {
  const options = ["React", "CSS", "SQL"];
  const [chosen, setChosen] = React.useState([]);

  function toggle(option) {
    setChosen(chosen.includes(option) ? chosen.filter((o) => o !== option) : [...chosen, option]);
  }

  return (
    <fieldset>
      <legend>Skills</legend>
      {options.map((option) => (
        <label key={option} style={{ display: "block" }}>
          <input type="checkbox" checked={chosen.includes(option)} onChange={() => toggle(option)} />
          {option}
        </label>
      ))}
      <p>Chosen: {chosen.length ? chosen.join(", ") : "none"}</p>
    </fieldset>
  );
}

Radio buttons: one value, compared with checked

All radio buttons in a group share a name. Each one is checked when the state equals its own value:

App.jsx
JSX
function App() {
  const [plan, setPlan] = React.useState("free");
  const plans = [
    { value: "free", label: "Free" },
    { value: "pro", label: "Pro" },
  ];

  return (
    <fieldset>
      <legend>Plan</legend>
      {plans.map((p) => (
        <label key={p.value} style={{ display: "block" }}>
          <input type="radio" name="plan" value={p.value} checked={plan === p.value} onChange={(e) => setPlan(e.target.value)} />
          {p.label}
        </label>
      ))}
      <p>Plan: {plan}</p>
    </fieldset>
  );
}

fieldset and legend give the group a name that screen readers announce.

Multiple select

<select multiple> takes an array as value, and you collect the selected options:

App.jsx
JSX
function App() {
  const [picked, setPicked] = React.useState(["b"]);

  function handleChange(e) {
    setPicked(Array.from(e.target.selectedOptions, (o) => o.value));
  }

  return (
    <div>
      <select multiple aria-label="Letters" value={picked} onChange={handleChange} style={{ height: 80 }}>
        <option value="a">A</option>
        <option value="b">B</option>
        <option value="c">C</option>
      </select>
      <p>Selected: {picked.join(", ")}</p>
    </div>
  );
}

For many selections, a group of checkboxes is often easier to use than a multiple select.

Quick reference

InputState holdsProps
text, email, password, number, datestringvalue, onChange
textareastringvalue, onChange
selectstringvalue on the select, onChange
one checkboxbooleanchecked, onChange (use e.target.checked)
checkbox grouparrayeach checked={arr.includes(x)}
radio groupstringeach checked={state === value}, same name
file(uncontrolled)read e.target.files

Key points

  • Text inputs, textarea and select use value; checkboxes and radios use checked.
  • Checkbox groups store an array; radio groups store one value.
  • Group related inputs in a fieldset with a legend.