Skip to content

Commit d52b116

Browse files
author
root
committed
Restore smooth countdown with requestAnimationFrame (milliseconds tick fast again)
Made-with: Cursor
1 parent 2769f28 commit d52b116

1 file changed

Lines changed: 7 additions & 12 deletions

File tree

src/features/countdown/hooks/useCountdown.ts

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,14 @@ const INITIAL_STATE: CountdownState = {
2121
isComplete: false,
2222
};
2323

24-
const ONE_SECOND = 1000;
25-
2624
export function useCountdown({
2725
targetTime,
2826
totalDuration,
2927
onComplete,
3028
onMilestone,
3129
}: UseCountdownOptions): CountdownState {
3230
const [state, setState] = useState<CountdownState>(INITIAL_STATE);
33-
const intervalRef = useRef<ReturnType<typeof setInterval> | null>(null);
31+
const rafRef = useRef<number>(0);
3432
const firedMilestones = useRef<Set<string>>(new Set());
3533

3634
const tick = useCallback(() => {
@@ -53,11 +51,11 @@ export function useCountdown({
5351
const fiveMin = 5 * 60 * 1000;
5452
const oneMin = 60 * 1000;
5553

56-
if (remaining <= fiveMin && remaining > fiveMin - 1000 && !firedMilestones.current.has("5min")) {
54+
if (remaining <= fiveMin && remaining > fiveMin - 150 && !firedMilestones.current.has("5min")) {
5755
firedMilestones.current.add("5min");
5856
onMilestone?.("5min");
5957
}
60-
if (remaining <= oneMin && remaining > oneMin - 1000 && !firedMilestones.current.has("1min")) {
58+
if (remaining <= oneMin && remaining > oneMin - 150 && !firedMilestones.current.has("1min")) {
6159
firedMilestones.current.add("1min");
6260
onMilestone?.("1min");
6361
}
@@ -71,6 +69,8 @@ export function useCountdown({
7169
progress,
7270
isComplete: false,
7371
});
72+
73+
rafRef.current = requestAnimationFrame(tick);
7474
}, [targetTime, totalDuration, onComplete, onMilestone]);
7575

7676
useEffect(() => {
@@ -80,15 +80,10 @@ export function useCountdown({
8080
}
8181

8282
firedMilestones.current.clear();
83-
tick();
84-
85-
intervalRef.current = setInterval(tick, ONE_SECOND);
83+
rafRef.current = requestAnimationFrame(tick);
8684

8785
return () => {
88-
if (intervalRef.current) {
89-
clearInterval(intervalRef.current);
90-
intervalRef.current = null;
91-
}
86+
if (rafRef.current) cancelAnimationFrame(rafRef.current);
9287
};
9388
}, [targetTime, tick]);
9489

0 commit comments

Comments
 (0)