npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

react-multi-page-form

v0.2.1

Published

Tools to handle multi-page forms

Downloads

112

Readme

React Multi Page Form

This is a tool for managing the sequence and flow of multi-page workflows. Given a long series of screens, it can put them in the proper order makes it easy to show and hide screens based on previous input.

Workflows can be composed, allowing you to reuse parts of a flow.

This should be used in combination with a component library and validation schema to improve your form management.

An integration with React Hook Form is provided, but the base could be used with any library.

View the docs

Basic Usage

  • Create an array of pages and/or sequences. One for each page of the form.
  • Set up react-hook-form
  • Pass the pages and the hook for API into useMultiPageHookForm to get the multi-page state and controls.
import { useForm } from 'react-hook-form';
import { useMultiPageHookForm } from 'react-multi-page-forms';

// create a list of pages for the form
const pages = [
    {
        id: 'first',
        Component: FirstPage,
    },
    {
        id: 'second',
        Component: SecondPage,
    },
]
const MyMultiPageForm = () => {
    // use react-hook-form's useForm
    const hookForm = useForm<FormModel>();
    
    // create multi-page controls
    const { 
        currentPage, // the page object
        advance, // goes to the next page, including completed pages
        advanceToNextIncomplete, // goes to the next incomplete page
        goBack, // goes back one page
        isFinal, // if this is the last page
        isFirst, // if this is the first page
    } = useMultiPageHookForm({
        hookForm,
        pages,
    });
    
    // render the component and controls
    return (<>
        <currentPage.Component
            errors={errors}
            register={register}
        />
    
        {!isFirst && <button onClick={goBack}>Prev</button>}
        {!isFinal ? (
            <button onClick={advance}>Next</button>
        ) : (
            <button type="submit">Submit</button>
        )}
    </>);
};

View the docs

Pages and Sequences

A page represents a single screen that will be shown to the user as part of this multi-step form. It can have as many fields or as few as you'd like. It can even have logic to show and hide fields built in.

A sequence is an array of pages and sequences that represent a specific flow. For example, they may be a series of screens specific to a certain country.

type FormPage<DataT, ComponentProps, ErrorList> = {
    id: string;
    // determines whether or not this page is needed
    isRequired?: (data: DeepPartial<DataT>) => boolean | undefined
    // determines if the page is already complete
    isComplete: (data: DeepPartial<DataT>) => boolean;
    // determines if this should be a final step in the flow
    isFinal?: (data: DeepPartial<DataT>) => boolean;
    // if you need to break the flow of the sequence, this makes that possible.
    // Undefined will go to the next page in the sequence
    selectNextPage?: (data: DeepPartial<DataT>) => Boolean
    // Mounted inputs are automatically validated.
    // If you need specific validation logic, put it here.
    validate?: (data: DeepPartial<DataT>) => ErrorList | undefined;
    // callback on arrival
    onArrive?: (data: DeepPartial<DataT>) => void;
    // callback on departure
    onExit?: (data: DeepPartial<DataT>) => Promise<void> | void;
    // the component that will be rendered
    Component: (props: ComponentProps) => JSX.Element;
};

export type FormSequence<DataT, ComponentProps, ErrorList> = {
    id: string;
    // an array of pages or sequences that make up this sequence
    pages: SequenceChild<DataT, ComponentProps, ErrorList>[];
    // determines if this sequence is needed
    isRequired?: isRequiredPredicate<DataT>;
};

export type DecisionNode<DataT> = {
    id: string,
    // determines whether or not this decision is needed
    isRequired?: (data: DeepPartial<DataT>) => boolean | undefined
    // where this node should redirect to. Undefined will go to the next page in the sequence
    selectNextPage?: (data: DeepPartial<DataT>) => Boolean
}

View the docs

A More Complete Example

import { useMultiPageHookForm } from 'react-multi-page-forms'

const pages = [
    {
        id: 'first',
        isComplete: (data) => !!data.name?.length,
        Component: FirstPage,
    },
    {
        id: 'second',
        isComplete: (data) => !!data.pet?.length,
        Component: SecondPage,
    },
]

export function MyMultiPageForm() {
    // set up React Hook Form
    const hookForm = useForm<FormModel>({});
    const {
        register,
        handleSubmit,
        formState: { errors },
    } = hookForm;
    
    // set up the multi-page controls
    const { 
        currentPage,
        advance,
        goBack,
        isFinal,
        isFirst
    } = useMultiPageHookForm({
        hookForm,
        pages: sequence,
    });
    
    const onSubmit: SubmitHandler<FormModel> = (data) => {
        console.log('submit', data);
    };
    
    return (
        <>
            <h1>Multi Page Form Example</h1>
            <form onSubmit={handleSubmit(onSubmit)}>
                <div className="card">
                    {/* render the current page */}
                    <currentPage.Component
                        errors={errors}
                        register={register}
                    />
                </div>
                <div className="card">
                    {!isFirst && <button onClick={goBack}>Prev</button>}
                    {!isFinal ? (
                        <button onClick={advance}>Next</button>
                    ) : (
                        <button type="submit">Submit</button>
                    )}
                </div>
            </form>
        </>
    );
}

View the docs