useStep()

A simple abstraction to play with a stepper, don't repeat yourself.

The Hook

1import { Dispatch, SetStateAction, useCallback, useMemo, useState } from 'react'
2
3interface Helpers {
4 goToNextStep: () => void
5 goToPrevStep: () => void
6 reset: () => void
7 canGoToNextStep: boolean
8 canGoToPrevStep: boolean
9 setStep: Dispatch<SetStateAction<number>>
10}
11
12function useStep(maxStep: number): [number, Helpers] {
13 const [currentStep, setCurrentStep] = useState(1)
14
15 const canGoToNextStep = useMemo(
16 () => currentStep + 1 <= maxStep,
17 [currentStep, maxStep],
18 )
19
20 const canGoToPrevStep = useMemo(() => currentStep - 1 >= 1, [currentStep])
21
22 const setStep = useCallback(
23 step => {
24 // Allow value to be a function so we have the same API as useState
25 const newStep = step instanceof Function ? step(currentStep) : step
26
27 if (newStep >= 1 && newStep <= maxStep) {
28 setCurrentStep(newStep)
29 return
30 }
31
32 throw new Error('Step not valid')
33 },
34 [maxStep, currentStep],
35 )
36
37 const goToNextStep = useCallback(() => {
38 if (canGoToNextStep) {
39 setCurrentStep(step => step + 1)
40 }
41 }, [canGoToNextStep])
42
43 const goToPrevStep = useCallback(() => {
44 if (canGoToPrevStep) {
45 setCurrentStep(step => step - 1)
46 }
47 }, [canGoToPrevStep])
48
49 const reset = useCallback(() => {
50 setCurrentStep(1)
51 }, [])
52
53 return [
54 currentStep,
55 {
56 goToNextStep,
57 goToPrevStep,
58 canGoToNextStep,
59 canGoToPrevStep,
60 setStep,
61 reset,
62 },
63 ]
64}
65
66export default useStep

Usage

1import React from 'react'
2
3import { useStep } from 'usehooks-ts'
4
5export default function Component() {
6 const [currentStep, helpers] = useStep(5)
7
8 const {
9 canGoToPrevStep,
10 canGoToNextStep,
11 goToNextStep,
12 goToPrevStep,
13 reset,
14 setStep,
15 } = helpers
16
17 return (
18 <>
19 <p>Current step is {currentStep}</p>
20 <p>Can go to previous step {canGoToPrevStep ? 'yes' : 'no'}</p>
21 <p>Can go to next step {canGoToNextStep ? 'yes' : 'no'}</p>
22 <button onClick={goToNextStep}>Go to next step</button>
23 <button onClick={goToPrevStep}>Go to previous step</button>
24 <button onClick={reset}>Reset</button>
25 <button onClick={() => setStep(3)}>Set to step 3</button>
26 </>
27 )
28}

Edit on CodeSandbox

See a way to make this page better?
Edit there »