dotUI
dotUI
beta
  1. Hooks
  2. Browser hooks
  3. useCounter

useCounter

Manage a counter value with minimum and maximum limits with useCounter.

"use client";

import { Button } from "@/lib/components/core/default/button";
import { useCounter } from "@/lib/hooks/use-counter";

function Demo() {
  const [count, { increment, decrement, set, reset }] = useCounter(3, {
    min: 0,
    max: 10,
  });
  return (
    <div>
      <p className="text-center text-fg-muted">startingValue: 3, min: 0, max: 10</p>
      <div className="mt-4 flex items-center gap-2">
        <Button onPress={increment} isDisabled={count >= 10}>
          Increment
        </Button>
        <Button onPress={decrement} isDisabled={count <= 0}>
          Decrement
        </Button>
        <Button
          onPress={() => {
            set(5);
          }}
        >
          Set to 5
        </Button>
        <Button onPress={reset}>Reset</Button>
      </div>
      <p className="mt-8 text-center text-4xl">{count}</p>
    </div>
  );
}

Installation

Copy and paste the following code into your project.

import React from "react";

export function useCounter(
  startingValue = 0,
  options: { min?: number; max?: number } = {}
): [
  number,
  {
    increment: () => void;
    decrement: () => void;
    set: (nextCount: number) => void;
    reset: () => void;
  },
] {
  const { min, max } = options;

  if (typeof min === "number" && startingValue < min) {
    throw new Error(`Your starting value of ${startingValue} is less than your min of ${min}.`);
  }

  if (typeof max === "number" && startingValue > max) {
    throw new Error(`Your starting value of ${startingValue} is greater than your max of ${max}.`);
  }

  const [count, setCount] = React.useState(startingValue);

  const increment = React.useCallback(() => {
    setCount((c) => {
      const nextCount = c + 1;

      if (typeof max === "number" && nextCount > max) {
        return c;
      }

      return nextCount;
    });
  }, [max]);

  const decrement = React.useCallback(() => {
    setCount((c) => {
      const nextCount = c - 1;

      if (typeof min === "number" && nextCount < min) {
        return c;
      }

      return nextCount;
    });
  }, [min]);

  const set = React.useCallback(
    (nextCount: number) => {
      setCount((c) => {
        if (typeof max === "number" && nextCount > max) {
          return c;
        }

        if (typeof min === "number" && nextCount < min) {
          return c;
        }

        return nextCount;
      });
    },
    [max, min]
  );

  const reset = React.useCallback(() => {
    setCount(startingValue);
  }, [startingValue]);

  return [
    count,
    {
      increment,
      decrement,
      set,
      reset,
    },
  ];
}

Update the import paths to match your project setup.

Parameters

NameTypeDescription
startingValue
number
The initial value for the counter. Default is 0.
options
object
Additional options for the counter.

The options object has the following properties:

NameTypeDescription
options.min
number
The minimum value allowed for the counter.
options.max
number
The maximum value allowed for the counter.

Return values

The useCounter hook returns an array with two elements:

NameTypeParamsDescription
[0]
number
The current value of the counter.
[1].increment
function
Increments the counter by 1.
[1].decrement
function
Decrements the counter by 1.
[1].set
function
nextCount: number
Sets the counter to the specified nextCount value.
[1].reset
function
Resets the counter to the initial startingValue.

Usage

const [count, { increment, decrement, set, reset }] = useCounter(0, {
  min: 0,
  max: 10,
});

Built by mehdibha. The source code is available on GitHub.