# Module: `src/hooks/useDebounce.ts` > **Source**: `src/hooks/useDebounce.ts` (12 lines) > **Topo batch**: B1 (leaf) ## Purpose Generic React hook that delays propagation of a rapidly-changing value to its consumers, used to throttle search inputs against the backend. ## Public interface ```ts export function useDebounce(value: T, delay: number): T ``` Returns the latest `value` only after `delay` milliseconds have elapsed without any further change. Generic in `T`, so callers can debounce strings, numbers, or any reference value (referential identity matters; see notes). ## Internal logic `useState(value)` for the debounced output; `useEffect` registers a `setTimeout(setDebounced, delay)` and returns a `clearTimeout` cleanup. The effect re-runs whenever `value` or `delay` changes — each new input value cancels the pending timeout from the previous render and starts a fresh one. ## Dependencies - **Internal**: none. - **External**: `react` (`useState`, `useEffect`). ## Consumers (intra-repo) - `src/features/annotations/MediaList.tsx` — debounces the media-name search input. - `src/features/dataset/DatasetPage.tsx` — debounces the dataset name-search filter (specified as 400ms in `_docs/ui_design/README.md` §"Dataset Explorer", but the actual delay is set by the caller). ## Data models None. ## Configuration None. ## External integrations None. ## Security None. ## Tests None. ## Notes / open questions - The hook compares values by referential equality (`useEffect` deps array). Passing a fresh object literal each render — e.g. `useDebounce({ q }, 300)` — would re-trigger the timer endlessly. Current callers pass primitives only; safe. - No "leading edge" / "trailing edge" / "max wait" knobs. Adequate for the two current consumers; if/when richer behaviour is needed, prefer `useDebouncedCallback` from a library over extending this module.