Skip to content

useCountup

React hook to create a countup functionality.

Add the hook via the CLI:

sh
npx @novajslabs/cli add useCountup
sh
npx @novajslabs/cli add useCountup
sh
pnpm dlx @novajslabs/cli add useCountup

Or copy and paste the code into your project:

ts
import { useState, useEffect } from "react";

interface Counter {
  current: string;
  isPaused: boolean;
  isOver: boolean;
  pause: () => void;
  play: () => void;
  reset: () => void;
  togglePause: () => void;
}

export const useCountup = (min: number, max: number): Counter => {
  const [count, setCount] = useState(min);
  const [paused, setPaused] = useState(false);
  const [isOver, setIsOver] = useState(false);

  useEffect(() => {
    if (paused) {
      return;
    }

    const interval = setInterval(() => {
      setCount((prev) => prev + 1);
    }, 1000);

    if (count >= max) {
      setIsOver(true);
      clearInterval(interval);
      return;
    }

    return () => clearInterval(interval);
  }, [count, min, max, paused]);

  return {
    current: count.toString(),
    isPaused: paused,
    isOver,
    pause: () => setPaused(true),
    play: () => setPaused(false),
    reset: () => {
      setIsOver(false);
      setCount(min);
    },
    togglePause: () => {
      setPaused(!paused);
    },
  };
};
js
import { useState, useEffect } from "react";

export const useCountup = (min, max) => {
  const [count, setCount] = useState(min);
  const [paused, setPaused] = useState(false);
  const [isOver, setIsOver] = useState(false);

  useEffect(() => {
    if (paused) {
      return;
    }

    const interval = setInterval(() => {
      setCount((prev) => prev + 1);
    }, 1000);

    if (count >= max) {
      setIsOver(true);
      clearInterval(interval);
      return;
    }

    return () => clearInterval(interval);
  }, [count, min, max, paused]);

  return {
    current: count.toString(),
    isPaused: paused,
    isOver,
    pause: () => setPaused(true),
    play: () => setPaused(false),
    reset: () => {
      setIsOver(false);
      setCount(min);
    },
    togglePause: () => {
      setPaused(!paused);
    },
  };
};

Requirements

React 16.8 or higher

Parameters

min required

  • Type: number

The initial value of the counter.

max required

  • Type: number

The final value of the counter.

Return values

current

  • Type: string

The current value of the counter.

isPaused

  • Type: boolean

Represents whether the counter is paused (true) or not (false).

isOver

  • Type: boolean

Represents whether the counter has ended paused (true) or not (false).

pause

  • Type: function

Pause the counter.

play

  • Type: function

Play the counter.

reset

  • Type: function

Reset the counter.

togglePause

  • Type: function

Toggle between pausing and playing the counter.

Example

tsx
import { useCountup } from "./hooks/useCountup";

const App = () => {
  const { current, isPaused, isOver, pause, play, reset, togglePause } =
    useCountup(0, 10);

  return (
    <div>
      <p>Counter value: {current}</p>
      <p>Is the counter paused? {isPaused ? "Yes" : "No"}</p>
      <p>Has the counter over? {isOver ? "Yes" : "No"}</p>
      <button onClick={pause}>Pause</button>
      <button onClick={play}>Play</button>
      <button onClick={reset}>Reset</button>
      <button onClick={togglePause}>Toggle Pause</button>
    </div>
  );
};

export default App;

Use cases

Here are some use cases where this React hook is useful:

  • Tracking elapsed time in a web-based workout timer
  • Implementing a real-time progress indicator for an online course completion tracker
  • Developing a time-tracking feature for billing hours in a freelance management tool
  • Integrating a countdown timer for an online exam platform
  • Adding a time-tracking feature to a project management tool for tracking task durations

Released under the MIT License.