Schedule use cases
import { useScheduledTimer } from '@crup/react-timer-hook/schedules';
Use schedules when a timer needs side effects on a cadence. updateIntervalMs is the fallback UI cadence. If a schedule is faster, the scheduler wakes at the schedule cadence so callbacks receive timely scheduledAt and firedAt context.
Poll backend status
const timer = useScheduledTimer({
autoStart: true,
updateIntervalMs: 1000,
endWhen: snapshot => snapshot.now >= expiresAt,
schedules: [
{
id: 'auction-status',
everyMs: 5000,
overlap: 'skip',
callback: async (_snapshot, controls) => {
const auction = await api.getAuction(auctionId);
if (auction.status === 'sold') controls.cancel('sold');
},
},
],
});
Use this for auction status checks, job status polling, order payment status, device heartbeat checks, and reservation validation.
Autosave heartbeat
const timer = useScheduledTimer({
autoStart: true,
schedules: [
{
id: 'autosave',
everyMs: 5000,
overlap: 'skip',
callback: () => saveDraft(),
onError: error => reportAutosaveError(error),
},
],
});
Use this for draft autosave, presence pings, collaborative editor heartbeats, and "last active" updates.
Use timing context
callback: async (_snapshot, _controls, context) => {
metrics.timing('poll.delay', context.firedAt - context.scheduledAt);
metrics.count('poll.overdue', context.overdueCount);
}
overdueCount tells you how many intervals were missed because the browser, JS thread, or callback work was late.
Stop the lifecycle from a schedule
schedules: [
{
id: 'payment-status',
everyMs: 3000,
callback: async (_snapshot, controls) => {
const payment = await api.getPayment(paymentId);
if (payment.status === 'paid') controls.cancel('paid');
if (payment.status === 'failed') controls.cancel('failed');
},
},
]
cancel(reason) is for terminal early stops. It does not call onEnd.
For live demos, see polling schedule, autosave heartbeat, poll and cancel, and backend event stop.