useSelection Hook

MediumReact Hooks20 min6 tests

Build a custom useSelection hook that manages a Set of selected ids, exposing toggle, isSelected, and a live count. Drive a small UI of toggle buttons whose pressed state and a status readout reflect the selection.

Implement a reusable useSelection() custom hook that tracks a set of selected ids and powers a tiny selection UI.

The hook returns { selected, toggle, isSelected, count }:

  • selected — the underlying Set of currently-selected ids.
  • toggle(id) — adds the id if it is not selected, removes it if it is. Toggling must be idempotent per click (clicking an unselected id selects it; clicking again deselects it).
  • isSelected(id) — returns a boolean for whether the id is currently selected.
  • count — the number of currently-selected ids.

The App renders three toggle buttons labeled Item a, Item b, and Item c (for ids a, b, c). Each button must expose its selected state through the aria-pressed attribute ("true" when selected, "false" when not), so assistive tech and tests can read it. A live region with role="status" always shows the current count in the form "{count} selected" (e.g. "0 selected", "2 selected").

State updates must be immutable — never mutate the existing Set in place; always derive a new Set so React re-renders correctly. The hook logic must live inside App.tsx and be consumed by the default-exported App component.

Requirements

  • Implement a custom hook useSelection() inside App.tsx returning { selected, toggle, isSelected, count }.
  • selected is a Set of ids; toggle(id) adds the id when absent and removes it when present, immutably (create a new Set each update).
  • isSelected(id) returns whether the id is currently in the selection; count returns selected.size.
  • Render three real <button> elements (Item a, Item b, Item c) for ids a/b/c, each with aria-pressed reflecting its selected state ('true' or 'false').
  • Render a role="status" live region showing exactly '{count} selected' that updates on every toggle.
  • Initial state: nothing selected — all buttons aria-pressed='false' and status reads '0 selected'.
Hints (3)
  1. Store state as a Set: const [selected, setSelected] = useState(() => new Set()). In toggle, copy it (const next = new Set(prev)) then next.has(id) ? next.delete(id) : next.add(id), and return next from the updater.
  2. Derive count from selected.size and isSelected from selected.has(id) on each render — no extra state needed.
  3. On each button set aria-pressed={isSelected(id)} (React serializes the boolean to the string 'true'/'false') and onClick={() => toggle(id)}.

Topics

  • React
  • React Hooks

Asked at

Myntra · BrowserStack · Swiggy · Dream11 · Rapido · Flipkart

Join Us
blur