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:
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
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
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
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
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
- Create three radio buttons for small, medium, and large pizza sizes.
- Give them the same
nameand different values. - Make medium selected initially.
- Create checkboxes for three pizza extras.
- Read the extras with
getAll(). - Create a required select for a delivery time.
- Connect its label with
useId(). - 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.