Skip to content

Instantly share code, notes, and snippets.

@krizh-p
Created June 22, 2025 15:06
Show Gist options
  • Save krizh-p/8ec3b7d10c6b6ad1470121c873c71b94 to your computer and use it in GitHub Desktop.
Save krizh-p/8ec3b7d10c6b6ad1470121c873c71b94 to your computer and use it in GitHub Desktop.
A React Hook to create multi-step shadcn forms
import { useCallback, useState } from "react";
type UseFormStepsProps = {
initialSteps: any[];
onStepValidation?: (step: any) => Promise<boolean> | boolean;
};
export type UseMultiFormStepsReturn = {
steps: any[];
currentStep: number;
currentStepData: any;
progress: number;
isFirstStep: boolean;
isLastStep: boolean;
goToNext: () => Promise<boolean>;
goToPrevious: () => void;
};
export function useMultiStepForm({
initialSteps,
onStepValidation,
}: UseFormStepsProps): UseMultiFormStepsReturn {
const steps = initialSteps;
const [currentStep, setCurrentStep] = useState(1);
const goToNext = useCallback(async () => {
const currentStepData = initialSteps[currentStep - 1];
if (onStepValidation) {
const isValid = await onStepValidation(currentStepData);
if (!isValid) return false;
}
if (currentStep < steps.length) {
setCurrentStep((prev) => prev + 1);
return true;
}
return false;
}, [currentStep, steps, onStepValidation, initialSteps]);
const goToPrevious = useCallback(() => {
if (currentStep > 1) {
setCurrentStep((prev) => prev - 1);
}
}, [currentStep]);
return {
steps,
currentStep,
currentStepData: steps[currentStep - 1],
progress: (currentStep / steps.length) * 100,
isFirstStep: currentStep === 1,
isLastStep: currentStep === steps.length,
goToNext,
goToPrevious,
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment