useTimeout.ts 1018 B

1234567891011121314151617181920212223242526272829303132333435363738394041424344
  1. import { useRef, useCallback, useEffect } from 'react';
  2. export const useTimeout = () => {
  3. const timeoutRef = useRef<ReturnType<typeof setTimeout>>();
  4. const callbackRef = useRef<() => void>();
  5. const set = useCallback((callback: () => void, delay: number) => {
  6. if (timeoutRef.current) {
  7. clearTimeout(timeoutRef.current);
  8. }
  9. callbackRef.current = callback;
  10. timeoutRef.current = setTimeout(callback, delay);
  11. }, []);
  12. const delay = useCallback((delay: number) => {
  13. if (timeoutRef.current) {
  14. clearTimeout(timeoutRef.current);
  15. }
  16. if (!callbackRef.current) {
  17. return;
  18. }
  19. timeoutRef.current = setTimeout(callbackRef.current, delay);
  20. }, []);
  21. const cancel = useCallback(() => {
  22. if (timeoutRef.current) {
  23. clearTimeout(timeoutRef.current);
  24. timeoutRef.current = undefined;
  25. callbackRef.current = undefined;
  26. }
  27. }, []);
  28. useEffect(
  29. () => () => {
  30. cancel();
  31. },
  32. [cancel],
  33. );
  34. return [set, cancel, delay] as const;
  35. };