# `useAudioFingerprint` — React hook for the fingerprint pipeline _(no submodules)_ ## Purpose `useAudioFingerprint(source, options?)` drives a `FingerprintBackend` off a React-managed `AudioDocument` and returns the live state, the resulting fingerprint when done, a `0..1` progress fraction, and any error encountered. The hook centralises the abort-on-unmount and progress wiring so component authors do not have to repeat that work across uploaders, visualisers, and match displays. ## Features - `source` can be `undefined`/`null` to mean "do nothing" — useful while waiting for an upload to decode. - `state` cycles through `'idle'` → `'fingerprinting'` → `'done'` (or `'error'`); a fresh source resets the cycle. - Abort-on-unmount and abort-on-source-change via internal `AbortController`. - Backend swap via `options.backend`; defaults to `LocalBackend`. - Wraps non-`ReactAudioFingerprintError` rejections in `FINGERPRINT_FAILED`. - Suppresses `ABORTED` errors — they settle back to `'idle'`. ## Usage: Basic Example ```tsx import { useAudioFingerprint } from "@suaveplan/react-audio-fingerprint/hooks/use-audio-fingerprint"; function FingerprintPreview({ doc }: { doc: AudioDocument }) { const { state, fingerprint, progress } = useAudioFingerprint(doc); if (state === "fingerprinting") return ; if (state === "done") return {fingerprint?.length} pairs; return null; } ``` ## Usage: Advanced Example Inject a custom backend (e.g. the optional Python backend) and surface errors: ```tsx import { useAudioFingerprint } from "@suaveplan/react-audio-fingerprint/hooks/use-audio-fingerprint"; function Surface({ doc, backend }: { doc: AudioDocument; backend: FingerprintBackend }) { const { state, error, fingerprint } = useAudioFingerprint(doc, { backend }); if (state === "error") return {error?.message}; if (state === "done") return ; return ; } ``` ## API Reference - `useAudioFingerprint(source, options?): UseAudioFingerprintResult`. - `source: AudioDocument | undefined | null`. - `options?: { backend?: FingerprintBackend }`. - `UseAudioFingerprintResult = { state, fingerprint, progress, error }`. - `state: 'idle' | 'fingerprinting' | 'done' | 'error'`. ## Implementation Notes The hook uses `useMemo` to stabilise the default `LocalBackend` so changing unrelated props does not retrigger the effect. The `alive` flag guarding all post-await `setState` calls is the canonical React pattern for protecting against the lifecycle race between an async fetch completing and a fast unmount. Aborts settle to `'idle'` (not `'error'`) so user-driven cancels do not produce a banner. Non-Suaveplan errors get wrapped so consumers can always discriminate via `error.code` without an `instanceof` chain.