UNPKG

@supunlakmal/hooks

Version:

A collection of reusable React hooks

68 lines 2.75 kB
import { useState, useEffect, useCallback, useRef } from 'react'; /** * Manages a countdown timer with start, pause, and reset controls. * * @param options Configuration options for the countdown timer. * @returns Controls and state for the countdown timer. */ export const useCountdown = ({ seconds, interval = 1000, onComplete, autoStart = true, }) => { const [remainingSeconds, setRemainingSeconds] = useState(seconds); const [isRunning, setIsRunning] = useState(autoStart); const intervalRef = useRef(null); const onCompleteRef = useRef(onComplete); useEffect(() => { onCompleteRef.current = onComplete; }, [onComplete]); const clearExistingInterval = useCallback(() => { if (intervalRef.current) { clearInterval(intervalRef.current); intervalRef.current = null; } }, []); const tick = useCallback(() => { setRemainingSeconds((prevSeconds) => { var _a; // Use interval seconds calculation instead of decrementing by 1 const secondsToDecrement = interval / 1000; if (prevSeconds <= secondsToDecrement) { clearExistingInterval(); setIsRunning(false); (_a = onCompleteRef.current) === null || _a === void 0 ? void 0 : _a.call(onCompleteRef); return 0; } return prevSeconds - secondsToDecrement; }); }, [interval, clearExistingInterval]); useEffect(() => { if (isRunning && remainingSeconds > 0) { intervalRef.current = setInterval(tick, interval); } else { clearExistingInterval(); } return clearExistingInterval; // Cleanup interval on unmount or when isRunning/interval changes }, [isRunning, interval, tick, remainingSeconds, clearExistingInterval]); const start = useCallback(() => { if (!isRunning && remainingSeconds > 0) { setIsRunning(true); } }, [isRunning, remainingSeconds]); const pause = useCallback(() => { if (isRunning) { setIsRunning(false); } }, [isRunning]); const reset = useCallback(() => { clearExistingInterval(); setRemainingSeconds(seconds); setIsRunning(autoStart); }, [seconds, autoStart, clearExistingInterval]); // Effect to handle changes in the initial seconds prop useEffect(() => { setRemainingSeconds(seconds); // Optionally restart timer if it was running // setIsRunning(autoStart); // Decided against auto-restart on prop change }, [seconds]); return { remainingSeconds, isRunning, start, pause, reset }; }; //# sourceMappingURL=useCountdown.js.map