Last active
November 2, 2022 20:52
-
-
Save amochkin/bbd509670018d508ed976ddd1f594935 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { useEffect, useRef, useState } from 'react'; | |
type TimerCallbackType = (timerLeft: number) => void; | |
/** | |
* useTimer hook to handle timer events. Has protection from subsequent calls, ie calling the timer when it was already started. | |
* @param callback Callback function | |
* @param timer Timer in milliseconds | |
* @param interval Interval between timer ticks in milliseconds | |
*/ | |
export const useTimer = (callback: TimerCallbackType, timer: number, interval: number = 1000) => { | |
const savedCallback = useRef<TimerCallbackType>(); | |
const [isActive, setIsActive] = useState<boolean>(false); | |
useEffect(() => { | |
savedCallback.current = callback; | |
}); | |
useEffect(() => { | |
function tick(left: number) { | |
const nextLeft = left - interval; | |
if (nextLeft >= interval) { | |
savedCallback.current && savedCallback.current(nextLeft); | |
setTimeout(() => tick(nextLeft), interval); | |
} else { | |
savedCallback.current && savedCallback.current(0); | |
setIsActive(false); | |
} | |
} | |
if (!isActive) { | |
setIsActive(true); | |
tick(timer); | |
} | |
// isActive is not a dependency because we don't want to restart the timer when it changes, | |
// so we disable the warning on the next line: | |
}, [interval, timer]); // eslint-disable-line react-hooks/exhaustive-deps | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Example: