UNPKG

@ducor/hooks

Version:

A collection of useful React hooks for building modern web applications. Includes hooks for clipboard operations, window events, intervals, timeouts, and more.

62 lines (61 loc) 2.11 kB
import { useCallback, useEffect, useRef } from "react"; /** * A robust timeout hook with manual control and auto-invocation options * @template T - Type of parameters passed to the callback * @param callback - Function to execute after delay * @param delay - Delay in milliseconds (null to disable) * @param options - Configuration options * @returns Object with control methods */ function useTimeout(callback, delay, options = { autoInvoke: false }) { const timeoutRef = useRef(null); const savedCallback = useRef(callback); const savedDelay = useRef(delay); // Always use the latest callback without resetting timeout useEffect(() => { savedCallback.current = callback; }, [callback]); // Update delay reference if it changes useEffect(() => { savedDelay.current = delay; }, [delay]); const clear = useCallback(() => { if (timeoutRef.current) { window.clearTimeout(timeoutRef.current); timeoutRef.current = null; } }, []); const start = useCallback((...args) => { clear(); if (savedDelay.current !== null) { timeoutRef.current = window.setTimeout(() => { savedCallback.current(...args); timeoutRef.current = null; }, savedDelay.current); } }, [clear]); const restart = useCallback((...args) => { clear(); start(...args); }, [clear, start]); // Handle auto-invocation and cleanup useEffect(() => { if (options.autoInvoke && delay !== null) { if (options.autoInvokeParams) { start(...options.autoInvokeParams); } else { // Safe cast since we know callback supports no params when autoInvokeParams isn't provided start(); } } return clear; }, [delay, options.autoInvoke, options.autoInvokeParams, start, clear]); return { start, clear, restart, isActive: () => timeoutRef.current !== null, }; } export default useTimeout;