← Back

React.js + Next.js · Module 3. Forms and Effects · Lesson 7 · Point 7

Radio Buttons, Checkboxes and Select

Text inputs let customers type their own answers.

Sometimes we want customers to choose from answers that we provide.

Pizza Palace can use:

  • radio buttons for one delivery method;
  • checkboxes for several optional extras;
  • a select menu for one delivery time.

All three controls work with React Form Actions and FormData.

We will learn one control at a time and then combine them in one order form.

First Look — The Three Controls in the Browser

Before looking at the code, see how these controls look to a Pizza Palace customer:

Radio buttons choose one option, checkboxes choose zero or several options, and a select opens a dropdown list.

You do not need to understand the code yet. First remember what each control looks like and how many choices it allows.


REACT · 01

1. Choose the Correct Form Control

Begin with one question:

How many choices may the customer select?

Customer Can Choose Use Pizza Palace Example
Exactly one visible choice Radio buttons Pickup or delivery
Zero, one, or several choices Checkboxes Extra cheese and olives
One choice from a compact list Select Delivery time

The simple rule is:

Radio  = one from a group
Checkbox = zero or many
Select = one from a dropdown

REACT · 02

2. Use Radio Buttons for One Choice

The customer must choose one delivery method.

File: src/components/DeliveryForm.tsx

export default function DeliveryForm() {
  // This function runs when the form is submitted.
  function handleSubmit(formData: FormData) {
    // Get the selected delivery method.
    const delivery = formData.get("delivery");

    // Show the result in the console.
    console.log("Delivery:", delivery);
  }

  return (
    <form action={handleSubmit}>
      <h3>Choose delivery method:</h3>

      <label>
        <input
          type="radio"
          name="delivery"
          value="pickup"
          defaultChecked
        />
        Pickup
      </label>

      <label>
        <input
          type="radio"
          name="delivery"
          value="courier"
        />
        Courier
      </label>

      <button type="submit">Continue</button>
    </form>
  );
}

Browser Result

Choose delivery method:

Submitted value

Delivery: pickup

Pickup is visible to the customer; pickup is submitted to FormData.

Why Does Only One Stay Selected?

Both radio buttons have the same name:

name="delivery"

The browser treats them as one group.

Their values are different:

value="pickup"
value="courier"

The value tells FormData which option was selected.


REACT · 03

3. Understand name, value, and defaultChecked

These three parts have different jobs:

Code Meaning
name="delivery" Put the radio buttons in one group
value="pickup" Submit pickup when this option is selected
defaultChecked Select this option when the form first appears

Read the selected radio value with get():

const delivery = formData.get("delivery");

Use get() because a radio group submits one selected value.

If nothing is selected, the result is null. Using defaultChecked gives the group a starting choice.

Common Radio Mistake

These are not one group because their names are different:

<input type="radio" name="pickup" value="pickup" />
<input type="radio" name="courier" value="courier" />

Remember:

Same name = one radio group
Different value = different options

REACT · 04

4. Use Checkboxes for Several Choices

A customer can choose more than one pizza extra.

File: src/components/ExtrasForm.tsx

export default function ExtrasForm() {
  function handleSubmit(formData: FormData) {
    const extras = formData.getAll("extras");

    console.log("Extras:", extras);
  }

  return (
    <form action={handleSubmit}>
      <fieldset>
        <legend>Pizza extras</legend>

        <label>
          <input
            type="checkbox"
            name="extras"
            value="extra-cheese"
          />
          Extra cheese
        </label>

        <label>
          <input
            type="checkbox"
            name="extras"
            value="olives"
          />
          Olives
        </label>

        <label>
          <input
            type="checkbox"
            name="extras"
            value="garlic-sauce"
          />
          Garlic sauce
        </label>
      </fieldset>

      <button type="submit">Add extras</button>
    </form>
  );
}

Browser Result

Pizza extras
Submitted values

Extras: ["extra-cheese", "olives"]

Checked boxes contribute values; unchecked boxes contribute nothing.

All checkboxes use name="extras", so we can collect their selected values together.

Unlike radio buttons, checkboxes do not turn each other off.


REACT · 05

5. Use getAll for Checkbox Groups

Use getAll() when one field name can have several submitted values:

const extras = formData.getAll("extras");

Possible results:

Nothing selected:
[]

Extra cheese selected:
["extra-cheese"]

Extra cheese and olives selected:
["extra-cheese", "olives"]

getAll() always returns an array. When nothing matches, it returns an empty array.

Compare the methods:

Method Result Use It For
formData.get("delivery") One value or null Radio group or select
formData.getAll("extras") An array Checkbox group

Check for One Specific Extra

function handleSubmit(formData: FormData) {
  const extras = formData.getAll("extras");
  const hasOlives = extras.includes("olives");

  console.log("Olives selected:", hasOlives);
}

An unchecked checkbox does not submit false. It simply adds no value.

Always provide a useful value. Without one, a checked checkbox normally submits the text on.


REACT · 06

6. Use Select for a Dropdown

A select menu saves space when the customer chooses one item from a list.

File: src/components/DeliveryTimeForm.tsx

import { useId } from "react";

export default function DeliveryTimeForm() {
  const deliveryTimeId = useId();

  function handleSubmit(formData: FormData) {
    const deliveryTime = formData.get("deliveryTime");

    if (typeof deliveryTime === "string") {
      console.log("Delivery time:", deliveryTime);
    }
  }

  return (
    <form action={handleSubmit}>
      <label htmlFor={deliveryTimeId}>Delivery time</label>

      <select
        id={deliveryTimeId}
        name="deliveryTime"
        defaultValue=""
        required
      >
        <option value="" disabled>
          Choose a delivery time
        </option>
        <option value="as-soon-as-possible">
          As soon as possible
        </option>
        <option value="18-00">18:00</option>
        <option value="19-00">19:00</option>
      </select>

      <button type="submit">Continue</button>
    </form>
  );
}

Browser Result

Submitted value

Delivery time: as-soon-as-possible

The customer sees descriptive text; FormData receives the option's value.

useId connects the label and select.

name="deliveryTime" gives the submitted field its name.

Each <option> has visible text and a submitted value.


REACT · 07

7. Understand defaultValue and required

defaultValue sets the select's first value:

<select name="deliveryTime" defaultValue="">

It selects the option whose value is an empty string:

<option value="">Choose a delivery time</option>

This looks like a placeholder, but a select does not have a real placeholder attribute.

If the customer must choose another option, use required and disable the empty option:

<select name="deliveryTime" defaultValue="" required>
  <option value="" disabled>
    Choose a delivery time
  </option>
  <option value="18-00">18:00</option>
</select>

Visible Text and Submitted Value

<option value="18-00">Today at 18:00</option>

The customer sees:

Today at 18:00

FormData receives:

18-00

The visible description can be friendly while the submitted value remains short and predictable.


REACT · 08

8. Combine Everything in One Pizza Order

Now use radio buttons, checkboxes, and a select in one form.

File: src/components/PizzaOptionsForm.tsx

import { useId } from "react";

export default function PizzaOptionsForm() {
  const formId = useId();
  const deliveryTimeId = formId + "-delivery-time";

  function handleOrder(formData: FormData) {
    const delivery = formData.get("delivery");
    const extras = formData.getAll("extras");
    const deliveryTime = formData.get("deliveryTime");

    console.log("Delivery:", delivery);
    console.log("Extras:", extras);
    console.log("Delivery time:", deliveryTime);
  }

  return (
    <form action={handleOrder}>
      <h2>Choose your order options</h2>

      <fieldset>
        <legend>Delivery method</legend>

        <label>
          <input
            type="radio"
            name="delivery"
            value="pickup"
            defaultChecked
          />
          Pickup
        </label>

        <label>
          <input
            type="radio"
            name="delivery"
            value="courier"
          />
          Courier
        </label>
      </fieldset>

      <fieldset>
        <legend>Pizza extras</legend>

        <label>
          <input
            type="checkbox"
            name="extras"
            value="extra-cheese"
          />
          Extra cheese
        </label>

        <label>
          <input
            type="checkbox"
            name="extras"
            value="olives"
          />
          Olives
        </label>
      </fieldset>

      <label htmlFor={deliveryTimeId}>Delivery time</label>
      <select
        id={deliveryTimeId}
        name="deliveryTime"
        defaultValue=""
        required
      >
        <option value="" disabled>Choose a time</option>
        <option value="as-soon-as-possible">
          As soon as possible
        </option>
        <option value="18-00">18:00</option>
      </select>

      <button type="submit">Place order</button>
    </form>
  );
}

Browser Result

Choose your order options

Delivery method
Pizza extras
Console output

Delivery: courier

Extras: ["extra-cheese", "olives"]

Delivery time: 18-00

One FormData object collects one radio value, several checkbox values, and one select value.

Follow the Submitted Data

get("delivery")       → "courier"
getAll("extras")      → ["extra-cheese", "olives"]
get("deliveryTime")   → "18-00"

This example collects the choices. A later backend request would check availability, calculate the price, and create the order.


REACT · 09

9. Fix Common Problems

Several Radio Buttons Stay Selected

Make sure every radio button in the group has the same name.

Only One Checkbox Value Appears

Use getAll("extras"), not get("extras").

Checkbox Submits on

Add a meaningful value:

value="extra-cheese"

Empty Select Is Accepted

Add required to the select and disabled to the empty option.

FormData Cannot Find the Control

Check the control's name. FormData does not read values by id.

Wrong Value Appears

Check the value attribute. The visible label or option text may be different from the submitted value.


REACT · 10

10. Summary and Practice

Final Comparison

Control Number of Choices FormData Method
Radio group One get()
Checkbox group Zero, one, or several getAll()
Select One get()

Important Properties

Property Job
name Groups values and identifies submitted data
value Defines the submitted value
defaultChecked Sets the initial radio or checkbox selection
defaultValue Sets the initial select value
required Prevents an empty required selection

Practice

  1. Create three radio buttons for small, medium, and large pizza sizes.
  2. Give them the same name and different values.
  3. Make medium selected initially.
  4. Create checkboxes for three pizza extras.
  5. Read the extras with getAll().
  6. Create a required select for a delivery time.
  7. Connect its label with useId().
  8. Combine the three controls and log their values.

Three Rules to Remember

Radio buttons: same name, one selected value
Checkboxes: getAll returns all selected values
Select: visible text and submitted value may differ

Next lesson: Wait for the next source topic before adding more Module 3 material.

← Back↑ Back to the top