React Use Precision Timer
Edit page
HomeDemo
Hooks
useDelayuseStopwatchuseTimerDescriptionUsageSignatureHow It WorksDemo
Code of ConductMIT License

useTimer

Description

A versatile precision timer hook for React. Doubles as a stopwatch.

See the live demo.

Usage

import { useTimer } from 'react-use-precision-timer';

Timer With Callback

In your function component:

// The callback will be called every 1000 milliseconds.
const timer = useTimer({ delay: 1000, callback: () => console.log("Boom") });

In a handler or effect:

timer.start();

Pass the hook a TimerOptions object to configure a timer's delay and the callback called when it fires. By default, the timer repeats.

You can also configure whether it should only run once (runOnce), whether it should fire immediately (fireImmediately), and whether it should start immediately (startImmediately).

The hook returns a Timer object. Using this, you can start, stop, pause, and resume a timer, and there are numerous accessors available for everything under the sun, from elapsed time to start time to whether the timer is running or paused.

Calling start while a timer is already running will restart it.

See all the ways to use a Timer below.

One Time Delay

// Two second delay, only runs one time, starts immediately
useTimer({ delay: 2000, callback: () => console.log("Boom"), runOnce: true, startImmediately: true });

This will call the callback after the provided delay, and only once. Alternatively, you can use the useDelay hook, which encapsulates these options.

Stopwatch Timer

// With no delay or callback, a timer acts as a stopwatch
const stopwatch = useTimer();

A timer with no delay option behaves exactly as a stopwatch. It will run forever until you pause or stop it, tracking the elapsed time.

You can start, stop, pause, and resume a stopwatch timer. You can retrieve elapsed time, total pause time, and more.

Alternatively, you can use the useStopwatch hook, which encapsulates this option.

Signature

useTimer(options?: TimerOptions) => Timer

Props

PropTypeDescription
optionsTimerOptionsOptions for the timer.

TimerOptions

All properties are optional.

PropertyTypeDescription
delaynumberAmount of time to wait before firing the timer, in milliseconds. Use undefined or 0 if you'd like the timer to behave as a stopwatch, never firing.
callback() => voidThe callback to call when the timer fires. Must provide a delay for the timer to fire.
runOncebooleanUse true to only run the timer once, false otherwise.
fireImmediatelybooleanUse true if the timer should fire immediately, calling the provided callback when starting. Use false otherwise.
startImmediatelybooleanUse true if the timer should start immediately, false if you'd like to call start() yourself.
fireOverdueCallbacksbooleanUse true to ensure the callback is always called the exact number of times expected, even when the timer is struggling to keep up due to a low delay or expensive callback. Use false otherwise. Default false. See below for more information.

Low Delays, Expensive Callbacks, and Overdue Calls

Very low delays (less than 10ms) and expensive callback operations can sometimes cause the timer to not fire fast enough. In these situations, timer events and calls to your callback can start to back up and become "overdue", leading to freezing or crashing.

As a failsafe, callback calls will be skipped when the timer can't keep up, allowing it to recover.

If you'd like, you can set the fireOverdueCallbacks timer option to true to disable this failsafe.

With no failsafe, the callback will always be called the exact number of times expected, even when calls are overdue. When calls are overdue, the callback will be called in loop to make up for missed fires.

Be aware that if the callback is expensive and always takes longer than the delay, this may lead to a crash.

Only set this to true if your callback doesn't consistently take longer than the delay and you are relying on a precise number of calls over time.

Return

The hook returns a Timer object. See below.

Timer

The Timer object returned by the hook has the following properties.

Mutators

PropertyTypeDescription
start() => voidStart the timer. If already started, will restart the timer.
stop() => voidStop the timer.
pause() => voidPause the timer.
resume() => voidResume the timer.

Getters

PropertyTypeDescription
isStarted() => booleanReturns true if the timer is started, false otherwise. Will be true when the timer is started but paused. Use isRunning() to check if the timer is started and not paused.
isStopped() => booleanReturns true if the timer is stopped, false otherwise. Will be false when the timer is started but paused.
isPaused() => booleanReturns true if the timer is started but paused, false otherwise.
isRunning() => booleanReturns true if the timer is started and not paused, false otherwise.
getStartTime() => numberReturn the time at which the timer was started, in milliseconds since the Unix epoch. Returns -1 if the timer is stopped.
getLastFireTime() => numberThe last time the timer fired and the callback was called, in milliseconds since the Unix epoch, or -1 if it hasn't fired yet or there is no delay.
getNextFireTime() => numberThe next time the timer will fire and the callback will be called, in milliseconds since the Unix epoch, or -1 if the timer is not running or there is no delay.
getPauseTime() => numberReturn the time at which the timer was paused, in milliseconds since the Unix epoch. Returns -1 if the timer is not paused or is stopped.
getResumeTime() => numberReturn the time at which the timer was last resumed, in milliseconds since the Unix epoch. Returns -1 if the timer is not started.
getRemainingTime() => numberReturn the time remaining in milliseconds before the timer fires. Returns 0 if the timer has no delay or is about to fire.
getElapsedStartedTime() => numberReturn the total amount of time elapsed in milliseconds since starting the timer, including paused time. Returns 0 if the timer is stopped.
getElapsedRunningTime() => numberReturn the amount of time that has elapsed in milliseconds since starting the timer, minus the time spent paused (if any). Returns 0 if the timer is stopped.
getTotalElapsedPausedTime() => numberReturn the total amount of time elapsed in milliseconds while paused since starting the timer. Returns 0 if the timer is stopped.
getPeriodElapsedPausedTime() => numberReturn the amount of time elapsed in milliseconds while paused in the current period. This will be the elapsed time since the timer last fired, or since it started if it hasn't fired yet. Returns 0 if never paused since starting or last firing.
getElapsedResumedTime() => numberReturn the total amount of time elapsed in milliseconds since the timer was last resumed, or since it was started if never paused. Returns 0 if the timer is stopped.

How It Works

The timer uses the start time and provided delay option to calculate the next fire time, and setTimeout() to home in on the exact fire time needed.

After firing, the next fire time is calculated by adding the delay to the previous fire time. This is how the timer avoids "wandering" from the start time due to inconsistencies with setTimeout().

If timer events become overdue due to very short delays (less than 10ms) and expensive callback operations, some callback calls may be skipped to allow the timer to recover, although you can disable this failsafe with the fireOverdueCallbacks option.

When used as a stopwatch (no delay), no timeouts are used.

Demo

See the live demo.