Skip to content

Instantly share code, notes, and snippets.

@Pro542
Last active February 12, 2020 07:10
Show Gist options
  • Save Pro542/3c0f35fabc0a02ed635c524107acb328 to your computer and use it in GitHub Desktop.
Save Pro542/3c0f35fabc0a02ed635c524107acb328 to your computer and use it in GitHub Desktop.
React timer hook with example
function useTimer(endTime: string, disableDays = false): [number, number, number, number] {
const [days, setDays] = useState<number>(0);
const [hours, setHours] = useState<number>(0);
const [minutes, setMinutes] = useState<number>(0);
const [seconds, setSeconds] = useState<number>(0);
useEffect(() => {
const timer = (interval: number): void => {
const countDownDate = new Date(endTime).getTime();
const now = new Date().getTime();
const distance = countDownDate - now;
const newDays = Math.floor(distance / (1000 * 60 * 60 * 24));
let newHours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
// If the days are disabled, add them to hours
if (disableDays) {
newHours = newDays * 24 + newHours;
}
const newMinutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
const newSeconds = Math.floor((distance % (1000 * 60)) / 1000);
if (distance < 0) {
if (interval) {
clearInterval(interval);
}
setDays(0);
setHours(0);
setMinutes(0);
setSeconds(0);
} else {
setDays(newDays);
setHours(newHours);
setMinutes(newMinutes);
setSeconds(newSeconds);
}
};
const interval = setInterval(timer, 1000);
return (): void => clearInterval(interval);
}, [disableDays, endTime]);
return [days, hours, minutes, seconds];
}
// Example usage
const Timer = ({ endTime, disableDays }) => {
const [days, hours, minutes, seconds] = useTimer(endTime, disableDays);
return <span>{days}:{hours}:{minutes}:{seconds}</span>;
}
@Pro542
Copy link
Author

Pro542 commented Jan 22, 2020

The way useEffect works here is similar to componentDidMount and componentWillUnmount; it sets the interval on mount and runs the returned function(cleanup function) to clear the interval on unmount.

The [] argument means tells that the effect doesn't depend on any input, and therefore runs only on mount.
If we use [endTime, disableDays], the effect will run for any changes in those variables.

@Pro542
Copy link
Author

Pro542 commented Feb 12, 2020

Updated according to the eslint rule exhaustive-deps. Timer function moves inside useEffect, and endTime, disableDays are given as dependencies for the effect

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment