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

2.2 KiB

hooks/use-midi-messages

(no submodules)

Purpose

useMidiMessages(selector, options?) exposes a bounded ring buffer of the most recent parsed MIDI messages from the selected input. It is a convenience built on top of useMidiInput for UI consumers that want to render a live activity feed (e.g. an "incoming messages" panel) or debug a controller wiring problem. The ring buffer trims the oldest entry once capacity is exceeded, so the array length is stable and the component can render it directly without further bookkeeping.

An optional filter whitelist accepts only specific message types into the buffer — handy when a device floods the bus with active- sensing or clock ticks the operator does not want in the visible log.

Features

  • Bounded ring buffer, default capacity 64.
  • Optional filter: readonly MidiMessageType[] whitelist.
  • Rebinds the underlying port.onMessage automatically when the port identity changes (plug/unplug, selector switch).
  • Buffer resets when the underlying port becomes null.

Usage: Basic

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

function ActivityLog() {
    const msgs = useMidiMessages("first", { capacity: 32 });
    return (
        <ul>
            {msgs.map((m, i) => (
                <li key={`${m.type}-${i}`}>{m.type}</li>
            ))}
        </ul>
    );
}

Usage: Advanced

function NotesOnly({ portId }: { portId: string }) {
    // Drop active-sensing/clock noise.
    const notes = useMidiMessages(portId, {
        filter: ["noteOn", "noteOff"],
        capacity: 128,
    });
    return <NoteRoll messages={notes} />;
}

API Reference

  • useMidiMessages(selector, options?): readonly MidiMessage[]
  • interface UseMidiMessagesOptions { capacity?, filter? }.

Implementation Notes

The internal state holds the ring buffer as a readonly MidiMessage[] rather than a Map or a separate write-cursor so consumers can drop straight into a .map(...) render. The buffer-replace path always allocates a fresh array (rather than mutating in place) so React detects the state change. The set-of-accepted-types is rebuilt only when the filter reference or the joined key changes, not per incoming message.