Skip to content

Custom use hooks to replace <Timer> #2313

@compulim

Description

@compulim

Feature request

Instead of using headless component, <Timer at={Date.now() + 1000} onInterval={() => 0} />. Create a new useTimer hook instead.

import { useEffect } from 'react';

export default function useTimer(at, fn) {
  useEffect(() => {
    const timeout = setTimeout(fn, Math.max(0, at - Date.now()));

    return () => clearTimeout(timeout);
  }, [at, fn]);
}

Also, we could do the same for RelativeTime, create a useIntervalSince function for the nextTimer() replacement.

import { useState } from 'react';

import useTimer from './useTimer';

function nextTimer(origin, interval) {
  const time = new Date(origin).getTime();
  const now = Date.now();

  return time > now ? time : now + interval - ((now - time) % interval);
}

export default function useIntervalSince(origin, interval, fn) {
  const [timer, setTimer] = useState(nextTimer(origin, interval));
  const handler = useCallback(() => {
    fn && fn();
    setTimer(nextTimer(origin, interval));
  }, [fn, origin, interval]);

  useTimer(timer, handler);
}

Also add tests, which use lolex to test against timestamp update.

Additional context

Do this after our "convert to React functional component" PR is merged.

[Enhancement]

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions