Newly Practicing Mortician

    react-use-wizard
    TypeScript icon, indicating that this package has built-in type declarations

    2.2.0 • Public • Published

    react-use-wizard logo

    react-use-wizard

    A React wizard (stepper) builder without the hassle, powered by hooks.

    ci version downloads minzipped size known vulnerabilities

    Features

    • Simplicity
    • Focused on logic
    • Zero dependencies
    • No UI restrictions
    • Tiny size
    • Written in TypeScript

    Installation

    yarn add react-use-wizard
    

    Quickstart

    import * as React from 'react';
    
    import { Wizard, useWizard } from 'react-use-wizard';
    
    const App = () => (
      <Wizard>
        <Step1 />
        <Step2 />
        <Step3 />
      </Wizard>
    );
    
    const Step1 = () => {
      const { handleStep, previousStep, nextStep } = useWizard();
    
      // Attach an optional handler
      handleStep(() => {
        alert('Going to step 2');
      });
    
      return (
        <>
          <button onClick={() => previousStep()}>Previous ⏮️</button>
          <button onClick={() => nextStep()}>Next ⏭</button>
        </>
      );
    };

    Links

    API

    Wizard

    Wizard is used to wrap your steps. Each child component will be treated as an individual step. You can pass a shared footer and header component that should always be in your steps.

    Example: pass a footer component that contains a "previous" and "next" button to the wizard.

    Props

    name type description required default
    startIndex number Indicate the wizard to start at the given step 0
    header React.ReactNode Header that is shown above the active step
    footer React.ReactNode Footer that is shown below the active stepstep
    wrapper React.React.ReactElement Optional wrapper that is exclusively wrapped around the active step component. It is not wrapped around the header and footer
    children React.ReactNode Each child component will be treated as an individual step ✔️

    Example

    // Example: show the active step in the header
    const Header = () => <p>I am the header component</p>;
    
    // Example: show the "previous" and "next" buttons in the footer
    const Footer = () => <p>I am the footer component</p>;
    
    // Example: Wrap steps in an `<AnimatePresence` from framer-motion 
    const Wrapper = () => <AnimatePresence exitBeforeEnter />;
    
    const App = () => {
      return (
        <Wizard 
            startIndex={0}
            header={<Header />}
            footer={<Footer />}
            wrapper={<Wrapper />}
          >
          <Step1 />
          <Step2 />
          <Step3 />
        </Wizard>
      );
    };

    useWizard

    Used to retrieve all methods and properties related to your wizard. Make sure Wizard is wrapped around your component when calling useWizard.

    handleStep is used to attach a handler to the step, can either be async or a sync function. This function will be invoked when calling nextStep.

    Remark - You can't use useWizard in the same component where Wizard is used.

    Methods

    name type description
    nextStep () => Promise Go to the next step
    previousStep () => void Go to the previous step index
    goToStep (stepIndex: number) => void Go to the given step index
    handleStep (handler: Handler) => void Attach a callback that will be called when calling nextStep. handler can be either sync or async
    isLoading boolean * Will reflect the handler promise state: will be true if the handler promise is pending and false when the handler is either fulfilled or rejected
    activeStep number The current active step of the wizard
    stepCount number The total number of steps of the wizard
    isFirstStep boolean Indicate if the current step is the first step (aka no previous step)
    isLastStep boolean Indicate if the current step is the last step (aka no next step)

    Example

    import * as React from 'react';
    
    import { Wizard, useWizard } from 'react-use-wizard';
    
    const App = () => (
      <Wizard>
        <Step1 />
        <Step2 />
        <Step3 />
      </Wizard>
    );
    
    const Step1 = () => {
      const {
        isLoading,
        isLastStep,
        isFirstStep,
        activeStep,
        stepCount,
        previousStep,
        nextStep,
        goToStep,
        handleStep,
      } = useWizard();
    
      // This handler is optional
      handleStep(() => {
        alert('Going to step 2');
      });
    
      return (
        <>
          <p>Step 1</p>
          {isLoading && <p>loading...</p>}
          <button onClick={() => previousStep()}>Previous</button>
          <button onClick={() => nextStep()}>Next</button>
          <button onClick={() => goToStep(2)}>Go to the last step</button>
          <div>
            Has next step: {!isLastStep ? '✅' : '⛔'}
            <br />
            Has previous step : {!isFirstStep ? '✅' : '⛔'}
          </div>
          Active step: {activeStep + 1} <br />
      );
    };

    It's recommended to pass the shared components to the header or footer in the Wizard to avoid duplication.

    Playground

    Small playground to showcase the functionalities of react-use-wizard: https://devrnt.github.io/react-use-wizard/

    Following use cases are available in the playground

    • Simple wizard with async and sync steps
    • Animated wizard with sync steps
    • Integration with react-query (mutation on next step)

    Source code can be found here.

    Examples

    Go to examples to check out some integrations (Gatsby, NextJS...).

    Async

    You can attach an async step handler to a step as well. Make sure to make to either pass an async function or return a promise (async) function:

    const Step1 = () => {
      const { handleStep } = useWizard();
    
      // Async function
      handleStep(async () => {
        await fetch(...);
      });
    
      // OR
    
      // Return promise
      handleStep(() => {
        return fetch(...);
      });
    
      ...
    }

    Errors

    If no errors are thrown then the wizard will go to the next step, so no need to call nextStep by yourself.

    If an error is thrown in the attached function the wizard will just stay at the same step and will rethrow the error. (So you can try-catch in your attached function).

    IsLoading

    If an async function is attached to handleStep the isLoading property will indicate the loading state of the function. In general isLoading will reflect the handler promise state: will be true if the handler promise is pending and false when the handler is either fulfilled or rejected.

    Animation

    Since react-use-wizard is focused to manage the logic of a wizard it doesn't mean you can't add some animation by your own. Add any animation library that you like. I highly suggest framer-motion to add your animations.

    Checkout this example to see how a step can be animated with framer motion.

    IE11

    Since Internet Explorer 11 doesn't support promises or async functions you'll need to install a polyfill for the regenerator-runtime.

    In general using react-app-polyfill is recommended, it includes polyfills for various browsers.

    Install

    npm i react-use-wizard

    DownloadsWeekly Downloads

    8,375

    Version

    2.2.0

    License

    MIT

    Unpacked Size

    60.2 kB

    Total Files

    26

    Last publish

    Collaborators

    • devrnt