useSelection React hook in TypeScript
v1.0.0Added in 1.0.0
A React selection hook for lists, tables and grids: single or multiple, Shift-click ranges, and select all with an indeterminate state.
Tick customers in the list; hold Shift and tick another to select everything between them. The header checkbox shows the indeterminate state and selects or clears all (the archived customer stays unselectable). Switch to single mode to pick one at a time; clicking it again clears it.
useSelection is a Pro React hook in the React hooks and utilities category, written in TypeScript for React 19. It installs as source with npx wingo-ui@latest add use-selection, together with useControllableState.
Add to a project
Requirements: React 19, in Next.js (App Router or Pages), Vite or React Router. Installation guide · Next.js setup · Vite setup
npx wingo-ui@latest add use-selectionuseSelection is part of Pro, with 298 more Pro items: $8 a month or $150 once. 14-day refund before you download any Pro item. See plans
Usage
Import useSelection from @/hooks/use-selection.
import { useSelection } from "@/hooks/use-selection"
const clients = [
{ id: "c1", name: "Northwind Tech LLC" },
{ id: "c2", name: "Summit Logistics Inc." },
{ id: "c3", name: "Greenleaf Pharmacy" },
]
export function ClientPicker() {
const selection = useSelection({ keys: clients.map((c) => c.id) })
return (
<ul>
{clients.map((client) => (
<li key={client.id}>
<label>
<input
type="checkbox"
checked={selection.isSelected(client.id)}
onClick={(event) => selection.handleSelect(client.id, event)}
readOnly
/>
{client.name}
</label>
</li>
))}
</ul>
)
}API
modedefault"multiple""single" | "multiple"single keeps at most one key (radio-like rows); multiple is for bulk actions.
allowDeselectdefaulttruebooleanSingle mode: selecting the selected key again clears the selection.
keys*readonly string[]Every selectable key in display order. Shift ranges walk this order; select all takes all of them.
value / defaultValue / onValueChangestring[]Controlled or uncontrolled through useControllableState. onValueChange gets the keys in display order.
disabledKeysreadonly string[]Keys that cannot be selected: toggle ignores them, ranges and select all skip them.
useSelection (result){ selected; isSelected(key); isDisabled(key); toggle(key, { range?, additive? }); handleSelect(key, event); select; deselect; selectRange(from, to); selectAll; clear; setSelected(keys); toggleAll; allSelected; someSelected; checkedState: boolean | "indeterminate"; count }handleSelect reads shiftKey from the click or key event (pass it straight from onClick / onCheckedChange's event). checkedState feeds a header Checkbox. Rendering stays yours: aria-selected / aria-checked and data-selected on the rows.
Parts
SelectionMode
type"single" | "multiple".
UseSelectionOptions
typeThe options object: keys, mode, value, defaultValue, onValueChange, disabledKeys and allowDeselect.
SelectionModifiers
typeThe second argument of toggle: { range?: boolean; additive?: boolean }.
UseSelectionResult
typeThe return value: selected keys, checks, actions, allSelected, someSelected, checkedState, count and handleSelect.
Examples
Bulk actions
Select invoices (Shift-click for a range) and the header turns into an action bar with the total.
Single choice cards
mode="single" with allowDeselect off: plan cards that always keep one selected.
Dependencies
Files
- hooks/use-selection.ts
FAQ
Is the useSelection hook free?
The preview, props and docs are free; copying the source needs a Pro plan. See plans.
How do I install useSelection?
Run npx wingo-ui@latest add use-selection. It also adds the Wingo UI item it builds on (useControllableState). With shadcn, add the @wingo-ui registry with your API key, then run npx shadcn@latest add @wingo-ui/use-selection.