All files / src/hooks useMomentUpdate.ts

93.75% Statements 30/32
81.81% Branches 9/11
90% Functions 9/10
93.54% Lines 29/31

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 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 583x 3x             3x       43x 43x 43x   43x 43x   43x   43x 6x 6x     43x 35x 6x   29x     29x 29x 2x   29x         43x 35x 29x   6x 5x 4x   6x 6x 1x          
import { useEffect, useReducer, useRef } from 'react';
import { useMomentContext } from '../MomentContext';
import type { MomentProps, PoolEntry } from '../types';
 
/**
 * Drives periodic re-renders for Moment formatting, mirroring the `<Moment>`
 * component's interval and pooled-timer lifecycle.
 */
export function useMomentUpdate(
  props: MomentProps,
  onTick?: (currentProps: MomentProps) => void
): void {
  const { pool } = useMomentContext();
  const propsRef = useRef<MomentProps>(props);
  propsRef.current = props;
 
  const onTickRef = useRef(onTick);
  onTickRef.current = onTick;
 
  const [, bump] = useReducer((n: number) => n + 1, 0);
 
  const triggerUpdate = useRef(() => {
    bump();
    onTickRef.current?.(propsRef.current);
  });
 
  useEffect(() => {
    if (pool) {
      return undefined;
    }
    Iif (props.interval === 0) {
      return undefined;
    }
    const intervalMs = props.interval ?? 60000;
    const timer = setInterval(() => {
      triggerUpdate.current();
    }, intervalMs);
    return () => {
      clearInterval(timer);
    };
  }, [pool, props.interval]);
 
  useEffect(() => {
    if (!pool) {
      return undefined;
    }
    const entry: PoolEntry = {
      getProps: () => propsRef.current,
      update: () => triggerUpdate.current()
    };
    pool.add(entry);
    return () => {
      pool.remove(entry);
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [pool]);
}