2023-08-29 11:50:38 +00:00
|
|
|
import { useEffect, useRef, useCallback } from "react";
|
2022-02-23 10:29:50 +00:00
|
|
|
|
|
|
|
export default function useSetTimeout() {
|
|
|
|
const didUnmountRef = useRef(false);
|
2023-08-29 11:50:38 +00:00
|
|
|
const scheduledTimersRef = useRef(new Set<number>());
|
2022-02-23 10:29:50 +00:00
|
|
|
|
2023-07-28 09:41:40 +00:00
|
|
|
useEffect(() => {
|
|
|
|
didUnmountRef.current = false;
|
|
|
|
|
|
|
|
return () => {
|
2022-02-23 10:29:50 +00:00
|
|
|
didUnmountRef.current = true;
|
|
|
|
clearAll();
|
2023-07-28 09:41:40 +00:00
|
|
|
};
|
|
|
|
}, []);
|
2022-02-23 10:29:50 +00:00
|
|
|
|
|
|
|
function clearAll() {
|
2023-08-29 11:50:38 +00:00
|
|
|
scheduledTimersRef.current.forEach((timer) => clearTimeout(timer));
|
|
|
|
scheduledTimersRef.current.clear();
|
2022-02-23 10:29:50 +00:00
|
|
|
}
|
|
|
|
|
2023-08-29 11:50:38 +00:00
|
|
|
return useCallback((callback: () => void, delay: number) => {
|
2022-02-23 10:29:50 +00:00
|
|
|
if (didUnmountRef.current) {
|
|
|
|
throw new Error("Can't schedule a timeout on an unmounted component.");
|
|
|
|
}
|
|
|
|
|
|
|
|
const timer = Number(setTimeout(handleCallback, delay));
|
|
|
|
|
2023-08-29 11:50:38 +00:00
|
|
|
scheduledTimersRef.current.add(timer);
|
2022-02-23 10:29:50 +00:00
|
|
|
|
|
|
|
function handleCallback() {
|
2023-08-29 11:50:38 +00:00
|
|
|
scheduledTimersRef.current.delete(timer);
|
2022-02-23 10:29:50 +00:00
|
|
|
callback();
|
|
|
|
}
|
2022-02-23 14:46:26 +00:00
|
|
|
|
|
|
|
return function cancelTimeout() {
|
|
|
|
clearTimeout(timer);
|
2023-08-29 11:50:38 +00:00
|
|
|
scheduledTimersRef.current.delete(timer);
|
2022-02-23 14:46:26 +00:00
|
|
|
};
|
2023-08-29 11:50:38 +00:00
|
|
|
}, []);
|
2022-02-23 10:29:50 +00:00
|
|
|
}
|