Skip to main content

Selectable List with “Select All”

Build a selectable list where each item has a checkbox and there is a "Select all" checkbox at the top. The user should be able to select or unselect items individually, or toggle all items at once using the "Select all" checkbox. When all items are selected, the "Select all" checkbox must appear as checked; when none are selected, it must appear as unchecked. If at least one item is selected, the total number of selected items should be displayed.

Input items: ["React", "Redux", "TypeScript"]

User actions:
1. Click "Select all"
→ Selected: ["React", "Redux", "TypeScript"]
→ "Select all" checked, selected count = 3

2. Uncheck "Redux"
→ Selected: ["React", "TypeScript"]
→ "Select all" unchecked, selected count = 2

3. Click "Select all" again
→ Selected: []
→ "Select all" unchecked, selected count = 0
import React, { useState, ChangeEvent } from 'react';

type SelectableListProps = {
items: string[];
};

export default function SelectableList({ items }: SelectableListProps) {
const [selected, setSelected] = useState<string[]>([]);

const areAllSelected = selected.length === items.length && items.length > 0;
const hasAnySelected = selected.length > 0;

const handleToggleItem = (item: string) => {
setSelected((prev) =>
prev.includes(item)
? prev.filter((value) => value !== item)
: [...prev, item]
);
};

const handleToggleAll = (event: ChangeEvent<HTMLInputElement>) => {
if (event.target.checked) {
setSelected(items);
} else {
setSelected([]);
}
};

return (
<div>
<h2>Selectable List</h2>

<label>
<input
type="checkbox"
checked={areAllSelected}
onChange={handleToggleAll}
/>
Select all
</label>

<ul>
{items.map((item) => {
const isChecked = selected.includes(item);

return (
<li key={item}>
<label>
<input
type="checkbox"
checked={isChecked}
onChange={() => handleToggleItem(item)}
/>
{item}
</label>
</li>
);
})}
</ul>

{hasAnySelected && (
<p>{selected.length} item(s) selected.</p>
)}
</div>
);
}