@qazuor/react-hooks
Version:
A comprehensive collection of production-ready React hooks for modern web applications. Features type-safe implementations, extensive testing, and zero dependencies. Includes hooks for state management, browser APIs, user interactions, and development uti
114 lines (99 loc) • 3.16 kB
text/typescript
import { useCallback, useEffect, useRef, useState } from 'react';
type UseIntervalOptions = {
/** The callback function to be called repeatedly. */
callback: () => void;
/** The time in milliseconds between each call. If `null`, the interval is paused. */
delay: number | null;
/** Whether to run the callback immediately when starting. Default is false. */
runImmediately?: boolean;
/** Whether to start the interval automatically. Default is true. */
autoStart?: boolean;
};
type UseIntervalReturn = {
/** Whether the interval is currently running */
isRunning: boolean;
/** Start or resume the interval */
start: () => void;
/** Pause the interval */
pause: () => void;
/** Reset and restart the interval */
restart: () => void;
};
/**
* useInterval
*
* @description This hook repeatedly executes a callback function at specified intervals.
* If `delay` is `null`, the interval will be paused.
*
* @param {UseIntervalOptions} options - Object containing:
* - `callback`: The function to be executed at each interval.
* - `delay`: The interval in milliseconds, or `null` to pause.
* - `runImmediately`: Whether to run callback immediately when starting.
* - `autoStart`: Whether to start interval automatically.
*
* @example
* ```ts
* useInterval({
* callback: () => {
* console.log('Repeating task every second');
* },
* delay: 1000,
* });
* ```
*
* @returns {UseIntervalReturn} An object containing:
* - `isRunning`: Whether the interval is active
* - `start`: Function to start/resume the interval
* - `pause`: Function to pause the interval
* - `restart`: Function to reset and restart the interval
*/
export function useInterval({
callback,
delay,
runImmediately = false,
autoStart = true
}: UseIntervalOptions): UseIntervalReturn {
const savedCallback = useRef(callback);
const [isRunning, setIsRunning] = useState(false);
const intervalId = useRef<number | null>(null);
useEffect(() => {
savedCallback.current = callback;
}, [callback]);
const cleanup = useCallback(() => {
if (intervalId.current !== null) {
clearInterval(intervalId.current);
intervalId.current = null;
}
}, []);
const start = useCallback(() => {
if (delay === null) {
setIsRunning(false);
return;
}
if (intervalId.current !== null) {
return;
}
setIsRunning(true);
if (runImmediately) {
savedCallback.current();
}
intervalId.current = window.setInterval(() => {
savedCallback.current();
}, delay);
}, [delay, runImmediately]);
const pause = useCallback(() => {
cleanup();
setIsRunning(false);
}, [cleanup]);
const restart = useCallback(() => {
cleanup();
start();
}, [cleanup, start]);
useEffect(() => {
if (autoStart) {
start();
}
return cleanup;
}, [autoStart, start, cleanup]);
return { isRunning, start, pause, restart };
}