useCounterSelection - Increment and Decrement number with fp-ts

16 December 2021

1 min read

Web development

This hook is an abstraction for storing a number value that can be incremented and decremented by a given amount of steps.

This hook uses Option and pipe from fp-ts.

useCounterSelection.ts
import { pipe } from "fp-ts/lib/function";
import * as O from "fp-ts/Option";
import { useState } from "react";

interface UseCounterProps {
  minValue?: number;
  maxValue?: number;
  selectedValueDefault: number;
  step?: number;
}

/**
 * Store a `number` value that can be incremented/decremented by the given amount of `step`.
 */
export const useCounterSelection = ({
  selectedValueDefault,
  maxValue,
  minValue,
  step = 1,
}: UseCounterProps): {
  selectedValue: number;
  onAddSelectedValue: () => void;
  onSubtractSelectedValue: () => void;
} => {
  const [selectedValue, setSelectedValue] = useState(selectedValueDefault);

  const onAddSelectedValue = (): void => {
    pipe(
      maxValue,
      O.fromNullable,
      O.fold(
        () => {
          setSelectedValue((v) => v + step);
        },
        (max) => {
          setSelectedValue((v) => Math.min(v + step, max));
        }
      )
    );
  };

  const onSubtractSelectedValue = (): void => {
    pipe(
      minValue,
      O.fromNullable,
      O.fold(
        () => {
          setSelectedValue((v) => v - step);
        },
        (min) => {
          setSelectedValue((v) => Math.max(v - step, min));
        }
      )
    );
  };

  return {
    selectedValue,
    onAddSelectedValue,
    onSubtractSelectedValue,
  };
};