# useCountdown > Self-stopping countdown or count-up timer. - Category: State - Package: `hookli` (install with `npm i hookli`) - Docs: https://hookli.vercel.app/docs/use-countdown ## Signature ```ts useCountdown(options: UseCountdownOptions): [number, UseCountdownActions] ``` ## Parameters - `options`: `UseCountdownOptions` — Configures the timer — start value, tick interval, direction and stop value. See below. ## Returns - `[0] count`: `number` — The current count. Ticks by ±1 every intervalMs while running. - `[1] actions`: `UseCountdownActions` — Start, pause and reset controls — see below. ## Types ### UseCountdownOptions The single options argument. - `countStart`: `number` — The value the countdown starts from. - `intervalMs`: `number` — Milliseconds between ticks. Defaults to 1000. - `isIncrement`: `boolean` — Count up instead of down. Defaults to false. - `countStop`: `number` — The value at which the timer stops itself. Defaults to 0. ### UseCountdownActions The second tuple element — the timer controls. - `startCountdown`: `() => void` — Starts (or resumes) the timer. - `stopCountdown`: `() => void` — Pauses the timer without resetting the count. - `resetCountdown`: `() => void` — Stops the timer and resets the count to countStart. ## Usage ```tsx import { useCountdown } from "hookli"; export function Demo() { const [count, { startCountdown, stopCountdown, resetCountdown }] = useCountdown({ countStart: 10, intervalMs: 1000, }); return (

{count}

); } ``` ## Source `src/hooks/use-countdown/use-countdown.ts` ```ts import { useCallback, useEffect, useRef, useState } from "react"; export interface UseCountdownOptions { countStart: number; intervalMs?: number; isIncrement?: boolean; countStop?: number; } export interface UseCountdownActions { startCountdown: () => void; stopCountdown: () => void; resetCountdown: () => void; } export const useCountdown = ({ countStart, intervalMs = 1000, isIncrement = false, countStop = 0, }: UseCountdownOptions): [number, UseCountdownActions] => { const [count, setCount] = useState(countStart); const [isRunning, setIsRunning] = useState(false); const startCountdown = useCallback(() => setIsRunning(true), []); const stopCountdown = useCallback(() => setIsRunning(false), []); const resetCountdown = useCallback(() => { setIsRunning(false); setCount(countStart); }, [countStart]); const tick = useRef(() => {}); tick.current = () => { setCount((prev) => (isIncrement ? prev + 1 : prev - 1)); }; useEffect(() => { if (isRunning && count === countStop) { setIsRunning(false); } }, [count, countStop, isRunning]); useEffect(() => { if (!isRunning) return; const id = setInterval(() => tick.current(), intervalMs); return () => clearInterval(id); }, [isRunning, intervalMs]); return [count, { startCountdown, stopCountdown, resetCountdown }]; }; ```