Files
skills/docs/ui/react/react-midi/src/hooks/use-midi/use-midi.md
2026-05-29 08:20:56 +01:00

2.3 KiB

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 ReadonlyMaps 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

import { useMidi } from "@suaveplan/react-midi";

function DeviceCounts() {
    const { status, inputs, outputs } = useMidi();
    if (status !== "granted") return <p>{status}</p>;
    return (
        <p>
            {inputs.length} ins / {outputs.length} outs
        </p>
    );
}

Usage: Advanced

function PermissionGate({ children }: { children: React.ReactNode }) {
    const { status, error } = useMidi();
    if (status === "loading") return <Spinner />;
    if (status === "unsupported")
        return <p>Web MIDI is not available in this browser.</p>;
    if (status === "denied")
        return <p>Permission denied: {error?.message}.</p>;
    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.