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

2.3 KiB

hooks/use-chain-plugin

(no submodules)

Purpose

useChainPlugin(trackId, slotIndex) returns the AudioFxPlugin currently occupying a specific slot in a track's PluginChain, or undefined if the slot is empty. It is the per-slot view of usePluginChain — useful for rendering a single <PluginSlot plugin={...} /> without re-rendering on every other slot's parameter change. The hook re-renders only when chain composition changes affect the targeted slot (plugin-added, plugin-removed, plugin-moved, plugin-replaced).

Features

  • useSyncExternalStore-based subscription to four chain events.
  • Returns undefined for out-of-range or empty slots — render-safe.
  • Stable behaviour across React 18+ concurrent rendering.
  • Listener cleanup on unmount.

Usage: Basic

import { useChainPlugin } from "@suaveplan/react-audio";

function SlotName({ trackId, slot }: { trackId: string; slot: number }) {
    const plugin = useChainPlugin(trackId, slot);
    return <span>{plugin?.metadata.name ?? "(empty)"}</span>;
}

Usage: Advanced

import { useChainPlugin, useParameter } from "@suaveplan/react-audio";

function SlotGain({ trackId, slot }: { trackId: string; slot: number }) {
    const plugin = useChainPlugin(trackId, slot);
    if (plugin === undefined) return null;
    return <ParameterKnob plugin={plugin} paramId="gain" />;
}

API Reference

  • useChainPlugin(trackId, slotIndex): AudioFxPlugin | undefined.

Implementation Notes

The hook subscribes to four chain events but reads only chain.plugins[slotIndex] in its snapshot, so React re-renders the consumer when (and only when) one of those events fires. Reading by index is O(1) on the chain's internal array. useSyncExternalStore returns the same plugin reference for the same slot across re-renders when nothing about that slot changed, so downstream useMemo / useEffect keyed on the plugin behave correctly. The hook ignores parameter-changed and bypass-changed events because they don't move the slot's plugin — for per-parameter subscriptions a child should use useParameter. The list of subscribed events therefore captures the smallest set of changes that could affect the value returned, keeping per-slot re-renders proportional to actual chain edits.