All files / src/components/SearchPanel useDelayedError.hook.ts

100% Statements 18/18
100% Branches 6/6
100% Functions 1/1
100% Lines 18/18

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 371x   1x                             1x 1x 21x 21x 21x   21x   21x 15x 10x 10x 10x 5x 5x 21x   21x 21x  
import { useEffect, useState } from 'react';
 
/**
 * Debounces a search-box error message so it only surfaces after the user pauses typing.
 * The message appears `delayMs` after the last change to `resetKey` (the live query text),
 * so every keystroke restarts the timer and the error never flashes mid-type. A cleared
 * error (`undefined`) hides immediately, with no lingering stale message.
 * @param error - The current error message, or `undefined` when the query is valid.
 * @param resetKey - A value that changes on every keystroke (the query text) to restart the timer.
 * @param delayMs - Idle time before the message is shown.
 * @returns The message to display, or `undefined` while typing / when valid.
 * @example
 * ```typescript
 * const hint = useDelayedError(searchError, query, 200);
 * // hint is undefined until the user stops typing for 200ms on an invalid query.
 * ```
 * @source
 */
export function useDelayedError(
  error: string | undefined,
  resetKey: string,
  delayMs: number,
): string | undefined {
  const [shown, setShown] = useState<string | undefined>(undefined);
 
  useEffect(() => {
    if (!error) {
      setShown(undefined);
      return;
    }
    const timer = setTimeout(() => setShown(error), delayMs);
    return () => clearTimeout(timer);
  }, [error, resetKey, delayMs]);
 
  return shown;
}