Skip to main content

All hooks

useStep

Custom hook that manages and navigates between steps in a multi-step process.


Usage

import { useStep } from './useStep'

export default function Component() {
  const [currentStep, helpers] = useStep(5)

  const {
    canGoToPrevStep,
    canGoToNextStep,
    goToNextStep,
    goToPrevStep,
    reset,
    setStep,
  } = helpers

  return (
    <>
      <p>Current step is {currentStep}</p>
      <p>Can go to previous step {canGoToPrevStep ? 'yes' : 'no'}</p>
      <p>Can go to next step {canGoToNextStep ? 'yes' : 'no'}</p>
      <button onClick={goToNextStep}>Go to next step</button>
      <button onClick={goToPrevStep}>Go to previous step</button>
      <button onClick={reset}>Reset</button>
      <button
        onClick={() => {
          setStep(3)
        }}
      >
        Set to step 3
      </button>
    </>
  )
}

API

function useStep(maxStep: number): unknown

Custom hook that manages and navigates between steps in a multi-step process.

Parameters

NameTypeDefault valueDescription
maxStepnumber-The maximum step in the process.

Returns

An tuple containing the current step and helper functions for navigating steps.

Type declaration

SetStepCallbackType

UseStepActions

Represents the second element of the output of the useStep hook.

NameTypeDescription
canGoToNextStepbooleanCheck if the next step is available.
canGoToPrevStepbooleanCheck if the previous step is available.
goToNextStep() => voidGo to the next step in the process.
goToPrevStep() => voidGo to the previous step in the process.
reset() => voidReset the step to the initial step.
setStepDispatch<SetStateAction<number>>Set the current step to a specific value.

Hook

import { useCallback, useState } from 'react'
import type { Dispatch, SetStateAction } from 'react'

/** Represents the second element of the output of the `useStep` hook. */
export type UseStepActions = {
  /** Go to the next step in the process. */
  goToNextStep: () => void
  /** Go to the previous step in the process. */
  goToPrevStep: () => void
  /** Reset the step to the initial step. */
  reset: () => void
  /** Check if the next step is available. */
  canGoToNextStep: boolean
  /** Check if the previous step is available. */
  canGoToPrevStep: boolean
  /** Set the current step to a specific value. */
  setStep: Dispatch<SetStateAction<number>>
}

export type SetStepCallbackType = (step: number | ((step: number) => number)) => void

/**
 * Custom hook that manages and navigates between steps in a multi-step process.
 * @param {number} maxStep - The maximum step in the process.
 * @returns {[number, UseStepActions]} An tuple containing the current step and helper functions for navigating steps.
 * @public
 * @see [Documentation](https://usehooks-ts.com/react-hook/use-step)
 * @example
 * ```tsx
 * const [currentStep, { goToNextStep, goToPrevStep, reset, canGoToNextStep, canGoToPrevStep, setStep }] = useStep(3);
 * // Access and use the current step and provided helper functions.
 * ```
 */
export function useStep(maxStep: number): [number, UseStepActions] {
  const [currentStep, setCurrentStep] = useState(1)

  const canGoToNextStep = currentStep + 1 <= maxStep
  const canGoToPrevStep = currentStep - 1 > 0

  const setStep = useCallback<SetStepCallbackType>(
    step => {
      // Allow value to be a function so we have the same API as useState
      const newStep = step instanceof Function ? step(currentStep) : step

      if (newStep >= 1 && newStep <= maxStep) {
        setCurrentStep(newStep)
        return
      }

      throw new Error('Step not valid')
    },
    [maxStep, currentStep],
  )

  const goToNextStep = useCallback(() => {
    if (canGoToNextStep) {
      setCurrentStep(step => step + 1)
    }
  }, [canGoToNextStep])

  const goToPrevStep = useCallback(() => {
    if (canGoToPrevStep) {
      setCurrentStep(step => step - 1)
    }
  }, [canGoToPrevStep])

  const reset = useCallback(() => {
    setCurrentStep(1)
  }, [])

  return [
    currentStep,
    {
      goToNextStep,
      goToPrevStep,
      canGoToNextStep,
      canGoToPrevStep,
      setStep,
      reset,
    },
  ]
}