All files / src/useClock useClockState.ts

100% Statements 14/14
71.42% Branches 5/7
100% Functions 5/5
100% Lines 14/14

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41                                    15x 10x     15x 15x 15x 5x 5x 5x   5x 5x 5x   5x 5x       15x    
import { useEffect, useReducer, useRef } from "react";
 
/**
 * Updates a state that provides the current instant at a defined frequency. By
 * default will initially set a timeout to update to the next frequency block
 * then run intervals at the frequencyMs specified after. This can be overriden
 * so that a different delay till the interval starts.
 *
 * @param frequencyMs - Frequency to run the updates defaults to 1000ms.
 * @param delayTillIntervalStart - Number of milliseconds to wait before the next
 *   frequency block, defaults to the next block based on the frequency. Note on
 *   Android this should not go past 60 seconds.
 * @returns Current instant
 */
export function useClockState(
  frequencyMs = 1000,
  delayTillIntervalStart?: number
): Date {
  const [now, updateNow] = useReducer<(r: number) => number>(
    () => Date.now(),
    Date.now()
  );
  const initialTimeoutRef = useRef<ReturnType<typeof setTimeout>>();
  const intervalRef = useRef<ReturnType<typeof setInterval>>();
  useEffect(() => {
    initialTimeoutRef.current = setTimeout(() => {
      updateNow();
      intervalRef.current = setInterval(updateNow, frequencyMs);
    }, delayTillIntervalStart ?? frequencyMs - (Date.now() % frequencyMs));
    return () => {
      Eif (initialTimeoutRef.current) {
        clearTimeout(initialTimeoutRef.current);
      }
      Eif (intervalRef.current) {
        clearInterval(intervalRef.current);
      }
    };
  }, [delayTillIntervalStart, frequencyMs]);
  return new Date(now);
}