import { useState, useEffect, useCallback, useRef } from "react"; export function useTimer() { const [elapsed, setElapsed] = useState(0); const startTimeRef = useRef(null); const rafRef = useRef(null); const startRef = useRef(() => { startTimeRef.current = performance.now(); function tick() { if (startTimeRef.current !== null) { setElapsed((performance.now() - startTimeRef.current) / 1000); rafRef.current = requestAnimationFrame(tick); } } rafRef.current = requestAnimationFrame(tick); }); const stopRef = useRef((): number => { let final = 0; if (startTimeRef.current !== null) { final = (performance.now() - startTimeRef.current) / 1000; setElapsed(final); } if (rafRef.current !== null) { cancelAnimationFrame(rafRef.current); rafRef.current = null; } startTimeRef.current = null; return final; }); const resetRef = useRef(() => { stopRef.current(); setElapsed(0); }); const start = useCallback(() => startRef.current(), []); const stop = useCallback(() => stopRef.current(), []); const reset = useCallback(() => resetRef.current(), []); useEffect( () => () => { if (rafRef.current !== null) cancelAnimationFrame(rafRef.current); }, [], ); return { elapsed, start, stop, reset }; }