# `hooks/use-audio-fx-plugin` _(no submodules)_ ## Purpose `useAudioFxPlugin(pluginType)` instantiates a plugin via the provider's `PluginRegistry.create(pluginType)` and memoises the result. The hook is the canonical way to obtain a one-off plugin instance (e.g. for a side-panel preview that is not in any chain). Consumers who want to insert the plugin into a chain pass the returned value to `usePluginChain(...).add(plugin)`. The hook does not own or register factories. The provider can auto-register factories via `options.plugins`; alternatively `useAudioEngine().registry.register(...)` lets consumers add factories dynamically. ## Features - Instance memoised by `pluginType` for component lifetime. - Throws `REACT_AUDIO.NO_PROVIDER` / `REACT_AUDIO.PROVIDER_PENDING` outside / before-init. - Throws `AudioFxError(AUDIO_FX.CHAIN_SLOT_NOT_FOUND)` if no factory is registered for `pluginType`. ## Usage: Basic ```tsx import { useAudioFxPlugin } from "@suaveplan/react-audio"; function PreviewEQ() { const eq = useAudioFxPlugin("equaliser"); return ; } ``` ## Usage: Advanced ```tsx import { useAudioEngine, useAudioFxPlugin, usePluginChain } from "@suaveplan/react-audio"; import { useEffect } from "react"; function EnsureRegistered() { const { registry } = useAudioEngine(); useEffect(() => { registry.register("delay", () => makeDelay()); }, [registry]); return null; } function ChainAdder({ trackId }: { trackId: string }) { const delay = useAudioFxPlugin("delay"); const { add } = usePluginChain(trackId); return ; } ``` ## API Reference - `useAudioFxPlugin(pluginType: string): AudioFxPlugin`. ## Implementation Notes The hook memoises on `[registry, pluginType]` so a remount of the provider (new registry identity) yields a fresh instance, but a re-render with the same provider and `pluginType` returns the same instance. The hook does not call `dispose()` on unmount because the plugin is typically inserted into a chain whose lifecycle owns the disposal. Consumers using the hook for a transient preview should call `plugin.dispose()` in their own `useEffect` cleanup. Plugins constructed by this hook are never auto-inserted into any chain — the caller is responsible for placement (e.g. via `usePluginChain(trackId).add(plugin)`). This separation lets the same hook back per-track inserts, side-panel previews, and one-off analyser taps.