diff --git a/packages/usehooks-ts/src/useStep/useStep.demo.tsx b/packages/usehooks-ts/src/useStep/useStep.demo.tsx
index 083f6239..ff82d9e9 100644
--- a/packages/usehooks-ts/src/useStep/useStep.demo.tsx
+++ b/packages/usehooks-ts/src/useStep/useStep.demo.tsx
@@ -1,7 +1,8 @@
import { useStep } from './useStep'
export default function Component() {
- const [currentStep, helpers] = useStep(5)
+ const initialStep = 2;
+ const [currentStep, helpers] = useStep(5, intitialStep)
const {
canGoToPrevStep,
@@ -14,6 +15,7 @@ export default function Component() {
return (
<>
+
Initial step is {initialStep}
Current step is {currentStep}
Can go to previous step {canGoToPrevStep ? 'yes' : 'no'}
Can go to next step {canGoToNextStep ? 'yes' : 'no'}
diff --git a/packages/usehooks-ts/src/useStep/useStep.test.ts b/packages/usehooks-ts/src/useStep/useStep.test.ts
index 092a100a..794b77eb 100644
--- a/packages/usehooks-ts/src/useStep/useStep.test.ts
+++ b/packages/usehooks-ts/src/useStep/useStep.test.ts
@@ -76,4 +76,31 @@ describe('useStep()', () => {
expect(result.current[1].canGoToNextStep).toBe(true)
})
+
+ it('should set inital step to 1 if max steps is exceeded', () => {
+ const { result } = renderHook(() => useStep(2, 3))
+
+ expect(result.current[0]).toBe(1)
+ })
+
+ it('should set inital step to 1 if inital step is below minimum', () => {
+ const { result } = renderHook(() => useStep(2, 0))
+
+ expect(result.current[0]).toBe(1)
+ })
+
+ it('should set inital step to 2', () => {
+ const { result } = renderHook(() => useStep(2, 2))
+
+ expect(result.current[0]).toBe(2)
+ })
+
+ it('should throw an error', () => {
+ const nonInteger = '' as never
+ vi.spyOn(console, 'error').mockImplementation(() => vi.fn())
+ expect(() => {
+ renderHook(() => useStep(2, nonInteger))
+ }).toThrowError(/initialStep must be an integer/)
+ vi.resetAllMocks()
+ })
})
diff --git a/packages/usehooks-ts/src/useStep/useStep.ts b/packages/usehooks-ts/src/useStep/useStep.ts
index 792f373a..60f66082 100644
--- a/packages/usehooks-ts/src/useStep/useStep.ts
+++ b/packages/usehooks-ts/src/useStep/useStep.ts
@@ -1,28 +1,29 @@
-import { useCallback, useState } from 'react'
+import { useCallback, useState } from "react";
-import type { Dispatch, SetStateAction } from 'react'
+import type { Dispatch, SetStateAction } from "react";
/** Represents the second element of the output of the `useStep` hook. */
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>
-}
+ /** 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>;
+};
-type SetStepCallbackType = (step: number | ((step: number) => number)) => void
+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.
+ * @param {number} [initialStep] - The initial step for the current step state (default is `1`).
* @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)
@@ -32,52 +33,58 @@ type SetStepCallbackType = (step: number | ((step: number) => number)) => void
* // Access and use the current step and provided helper functions.
* ```
*/
-export function useStep(maxStep: number): [number, UseStepActions] {
- const [currentStep, setCurrentStep] = useState(1)
+export function useStep(
+ maxStep: number,
+ initialStep = 1,
+): [number, UseStepActions] {
+ if (!Number.isInteger(initialStep)) {
+ throw new Error('initialStep must be an integer');
+ }
+ const [currentStep, setCurrentStep] = useState(initialStep > 0 && initialStep <= maxStep ? initialStep : 1);
- const canGoToNextStep = currentStep + 1 <= maxStep
- const canGoToPrevStep = currentStep - 1 > 0
+ const canGoToNextStep = currentStep + 1 <= maxStep;
+ const canGoToPrevStep = currentStep - 1 > 0;
- const setStep = useCallback(
- step => {
- // Allow value to be a function so we have the same API as useState
- const newStep = step instanceof Function ? step(currentStep) : step
+ const setStep = useCallback(
+ (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
- }
+ if (newStep >= 1 && newStep <= maxStep) {
+ setCurrentStep(newStep);
+ return;
+ }
- throw new Error('Step not valid')
- },
- [maxStep, currentStep],
- )
+ throw new Error("Step not valid");
+ },
+ [maxStep, currentStep],
+ );
- const goToNextStep = useCallback(() => {
- if (canGoToNextStep) {
- setCurrentStep(step => step + 1)
- }
- }, [canGoToNextStep])
+ const goToNextStep = useCallback(() => {
+ if (canGoToNextStep) {
+ setCurrentStep((step) => step + 1);
+ }
+ }, [canGoToNextStep]);
- const goToPrevStep = useCallback(() => {
- if (canGoToPrevStep) {
- setCurrentStep(step => step - 1)
- }
- }, [canGoToPrevStep])
+ const goToPrevStep = useCallback(() => {
+ if (canGoToPrevStep) {
+ setCurrentStep((step) => step - 1);
+ }
+ }, [canGoToPrevStep]);
- const reset = useCallback(() => {
- setCurrentStep(1)
- }, [])
+ const reset = useCallback(() => {
+ setCurrentStep(1);
+ }, []);
- return [
- currentStep,
- {
- goToNextStep,
- goToPrevStep,
- canGoToNextStep,
- canGoToPrevStep,
- setStep,
- reset,
- },
- ]
+ return [
+ currentStep,
+ {
+ goToNextStep,
+ goToPrevStep,
+ canGoToNextStep,
+ canGoToPrevStep,
+ setStep,
+ reset,
+ },
+ ];
}