0.0.8 • Published 9 months ago

react-zod-multistep-form v0.0.8

Weekly downloads
-
License
Apache-2.0
Repository
github
Last release
9 months ago

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 and goToPreviousStep functions to handle form step transitions while respecting validation.
  • Field-specific validation: Uses trigger from react-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

  1. Define a Zod schema: This schema validates each step of your form.
  2. Create form step components: Use the FormStepComponent type to build form components that handle form fields and errors.
  3. Define form steps: Create an array of objects where each object contains a component and fields that correspond to the Zod schema.
  4. Use the useMultiStepForm hook: Manage form state, navigation, and validation across steps.
  5. Render the form: Use the hook's goToNextStep and goToPreviousStep functions to control navigation between steps.

API Reference

Parameters

The useMultiStepForm hook accepts the following parameters:

  • steps: An array of form steps, each with a component and a list of fields 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 from react-hook-form.
  • control: The control object from react-hook-form for managing form fields.
  • errors: An object containing validation errors for each form field.
  • register: The register function from react-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!

0.0.8

9 months ago

0.0.7

9 months ago

0.0.6

9 months ago

0.0.5

9 months ago

0.0.4

9 months ago

0.0.3

9 months ago

0.0.2

9 months ago

0.0.1

9 months ago