# `hooks/use-midi` _(no submodules)_ ## Purpose `useMidi()` is the most general hook in `@suaveplan/react-midi`. It returns the live `MidiContextValue` surface as `{ status, access, inputs, outputs, error }`, where `inputs` and `outputs` are arrays freshly materialised from the underlying `ReadonlyMap`s whenever the provider's `stateVersion` advances (i.e. whenever a port plugs or unplugs). Components that only need status or device-list snapshots can reach for this hook directly; specialised hooks (`useMidiInput`, `useMidiDevices`) wrap it for narrower use-cases. The hook never throws on a `denied` / `unsupported` status — it *reports* the state. The only throw is the structural `REACT_MIDI.NO_PROVIDER` when rendered outside a provider. ## Features - One snapshot of status, access, inputs, outputs, and last error. - Arrays re-materialise on `stateVersion` bumps; stable identity between bumps so consumers can pass them straight to `key`. - Returns empty arrays during `loading` / `denied` / `unsupported`. ## Usage: Basic ```tsx import { useMidi } from "@suaveplan/react-midi"; function DeviceCounts() { const { status, inputs, outputs } = useMidi(); if (status !== "granted") return

{status}

; return (

{inputs.length} ins / {outputs.length} outs

); } ``` ## Usage: Advanced ```tsx function PermissionGate({ children }: { children: React.ReactNode }) { const { status, error } = useMidi(); if (status === "loading") return ; if (status === "unsupported") return

Web MIDI is not available in this browser.

; if (status === "denied") return

Permission denied: {error?.message}.

; return <>{children}; } ``` ## API Reference - `useMidi(): UseMidiResult` - `interface UseMidiResult { status, access, inputs, outputs, error }`. ## Implementation Notes The hook materialises `Array.from(access.inputs.values())` only when either `access` (root identity) or `stateVersion` (plug/unplug counter) changes — `useMemo` keys both into the dep list. This means consumers that pass `inputs.length` to a downstream effect avoid the "every render is a new array" trap that a naïve `[...map.values()]` would create.