react-zod-multistep-form
v0.0.8
Published
A React hook for managing multi-step forms with Zod schema validation and react-hook-form integration. Simplifies navigation between form steps, handles form state, validation, and error management with ease.
Downloads
16
Maintainers
Readme
React Zod Multi-Step Form Hook
react-zod-multistep-form
is a lightweight React hook designed to simplify the
management of multi-step forms. It integrates react-hook-form
with Zod
schema validation to handle form state, validation, and error management across
multiple steps. This hook provides a seamless way to navigate between form steps
while maintaining robust validation and form control.
Features
- Multi-step form management: Easily navigate through multiple form steps with built-in state management.
- Zod schema validation: Integrates
Zod
for schema-based validation at each step to ensure type safety. - React Hook Form integration: Leverages
react-hook-form
to handle form state, registration, and validation. - Error handling: Provides detailed error management for each form step, ensuring validation is respected.
- Navigation callbacks: Simple
goToNextStep
andgoToPreviousStep
functions to handle form step transitions while respecting validation. - Field-specific validation: Uses
trigger
fromreact-hook-form
to validate only the fields in the current step before allowing navigation to the next step.
Installation
npm install react-zod-multistep-form
Usage
Here’s how to use the useMultiStepForm
hook in your application:
Step 1: Define your form schema using Zod
import { z } from "zod";
const schema = z.object({
name: z.string().min(2, "Name is required"),
age: z.number().min(18, "Must be at least 18"),
});
type FormData = z.infer<typeof schema>;
Step 2: Create form step components
import { StepComponent } from "react-zod-multistep-form";
const NameStep: StepComponent<FormData> = ({ register, errors }) => (
<div>
<label>Name</label>
<input {...register("name")} />
{errors.name && <p>{errors.name.message}</p>}
</div>
);
const AgeStep: StepComponent<FormData> = ({ register, errors }) => (
<div>
<label>Age</label>
<input type="number" {...register("age")} />
{errors.age && <p>{errors.age.message}</p>}
</div>
);
Step 3: Define your form steps
const steps: Step<FormData>[] = [
{ component: NameStep, fields: ["name"] },
{ component: AgeStep, fields: ["age"] },
];
Step 4: Use useMultiStepForm
in your form component
import useMultiStepForm from "react-zod-multistep-form";
const MultiStepForm = () => {
const {
CurrentStep,
goToNextStep,
goToPreviousStep,
isFirstStep,
isLastStep,
handleSubmit,
control,
errors,
register,
} = useMultiStepForm<FormData>({
steps,
schema,
initialValues: { name: "", age: 0 },
});
const onSubmit = (data: FormData) => {
console.log(data);
};
return (
<form noValidate onSubmit={handleSubmit(onSubmit)}>
<CurrentStep control={control} register={register} errors={errors} />
{!isFirstStep && (
<button type="button" onClick={() => goToPreviousStep()}>
Back
</button>
)}
{!isLastStep && (
<button type="button" onClick={() => goToNextStep()}>
Next
</button>
)}
{isLastStep && <button type="submit">Submit</button>}
</form>
);
};
Using trigger
for Field-Specific Validation
The useMultiStepForm
hook leverages react-hook-form
's trigger
function to
validate only the fields present in the current step before moving to the next
one. This ensures that each form step only validates the fields it's responsible
for, enhancing performance and making the validation process more intuitive.
In the goToNextStep
function, the trigger
method is used with the list of
fields from the current step, which ensures that only the fields in that step
are validated before the form transitions to the next step. If validation fails,
the user is not allowed to move to the next step until the errors are resolved.
Example:
const goToNextStep = useCallback(async () => {
const isValid = await trigger(steps[currentStepIndex].fields); // Only validate current step fields
if (!isValid) return;
setCurrentStepIndex((prevStep) =>
prevStep < steps.length - 1 ? prevStep + 1 : prevStep
);
}, [currentStepIndex, steps, trigger]);
This approach ensures that each form step only validates the relevant fields, which makes the process more efficient and prevents unnecessary validation across the entire form.
Optional: Separate out Navigation Button logic
type FormNavButtonsProps = {
goToPreviousStep: () => void;
goToNextStep: () => Promise<void>;
isFirstStep: boolean;
isLastStep: boolean;
};
export const FormNavButtons: React.FC<FormNavButtonsProps> = ({
goToPreviousStep,
goToNextStep,
isFirstStep,
isLastStep,
}) => {
return (
<nav>
{!isFirstStep && (
<button type="button" onClick={goToPreviousStep}>
Back
</button>
)}
{!isLastStep && (
<button type="button" onClick={goToNextStep}>
Next
</button>
)}
{isLastStep && <button type="submit">Submit</button>}
</nav>
);
};
Step-by-Step Guide
- Define a Zod schema: This schema validates each step of your form.
- Create form step components: Use the
FormStepComponent
type to build form components that handle form fields and errors. - Define form steps: Create an array of objects where each object contains
a
component
andfields
that correspond to the Zod schema. - Use the
useMultiStepForm
hook: Manage form state, navigation, and validation across steps. - Render the form: Use the hook's
goToNextStep
andgoToPreviousStep
functions to control navigation between steps.
API Reference
Parameters
The useMultiStepForm
hook accepts the following parameters:
steps
: An array of form steps, each with acomponent
and a list offields
to validate.schema
: A Zod schema that defines the structure and validation rules for your form data.initialValues
: The initial values for each form field.
The hook also accepts a generic type that can be inferred from your Zod schema, allowing for type-safe form handling.
Return Values
The hook returns an object containing the following properties:
CurrentStep
: The current form step component to render.currentStepIndex
: The index of the current step.setCurrentStepIndex
: A function to manually set the current step index.goToNextStep
: Function to move to the next step, ensuring the current step's validation passes.goToPreviousStep
: Function to move to the previous step.isFirstStep
: Boolean indicating if the current step is the first step.isLastStep
: Boolean indicating if the current step is the last step.handleSubmit
: The form submission handler fromreact-hook-form
.control
: Thecontrol
object fromreact-hook-form
for managing form fields.errors
: An object containing validation errors for each form field.register
: Theregister
function fromreact-hook-form
for registering form fields.
License
This project is licensed under the Apache License 2.0.
This package simplifies the process of building multi-step forms with Zod validation in React. If you encounter any issues or have suggestions for improvements, feel free to open an issue or contribute to the repository!