Skip to content

toss/use-funnel

Folders and files

NameName
Last commit message
Last commit date

Latest commit

83d8afd · Feb 24, 2025

History

84 Commits
Feb 24, 2025
Feb 15, 2025
Jul 25, 2024
Nov 20, 2024
Feb 24, 2025
Feb 24, 2025
Feb 24, 2025
Jul 25, 2024
Jul 25, 2024
Jul 25, 2024
Jul 25, 2024
Jul 25, 2024
Jul 25, 2024
Jul 25, 2024
Aug 16, 2024
Aug 16, 2024
Aug 16, 2024
Feb 15, 2025
Aug 19, 2024
Feb 15, 2025
Sep 27, 2024

Repository files navigation

@use-funnel

A powerful and safe step-by-step state management library

MIT License Discord Badge

@use-funnel is a React Hook that helps you easily implement complex UI flows.

Core Concepts

Strong Type Support

By comparing the type of the current step with the next, you can ensure that only the required states are managed safely.

State Management by History

Manage states based on history, making it easy to handle backward and forward navigation.

Various Router Support

Supports browser history, react-router, next.js, @react-navigation/native, and more.

Example

use-funnel-example.mp4
import { useFunnel } from '@use-funnel/browser';

export function App() {
  const funnel = useFunnel<{
    SelectJob: { jobType?: 'STUDENT' | 'EMPLOYEE' };
    SelectSchool: { jobType: 'STUDENT'; school?: string };
    SelectEmployee: { jobType: 'EMPLOYEE'; company?: string };
    EnterJoinDate: { jobType: 'STUDENT'; school: string } | { jobType: 'EMPLOYEE'; company: string };
    Confirm: ({ jobType: 'STUDENT'; school: string } | { jobType: 'EMPLOYEE'; company: string }) & { joinDate: string };
  }>({
    id: 'hello-world',
    initial: {
      step: 'SelectJob',
      context: {},
    },
  });

  return (
    <funnel.Render
      SelectJob={funnel.Render.with({
        events: {
          selectSchool: (_, { history }) => history.push('SelectSchool', { jobType: 'STUDENT' }),
          selectEmployee: (_, { history }) => history.push('SelectEmployee', { jobType: 'EMPLOYEE' }),
        },
        render({ dispatch }) {
          return (
            <SelectJob
              onSelectSchool={() => dispatch('selectSchool')}
              onSelectEmployee={() => dispatch('selectEmployee')}
            />
          );
        },
      })}
      SelectSchool={({ history }) => (
        <SelectSchool
          onNext={(school) =>
            history.push('EnterJoinDate', (prev) => ({
              ...prev,
              school,
            }))
          }
        />
      )}
      SelectEmployee={({ history }) => (
        <SelectEmployee
          onNext={(company) =>
            history.push('EnterJoinDate', (prev) => ({
              ...prev,
              company,
            }))
          }
        />
      )}
      EnterJoinDate={funnel.Render.overlay({
        render({ history, close }) {
          return (
            <EnterJoinDateBottomSheet
              onNext={(joinDate) => history.push('Confirm', { joinDate })}
              onClose={() => close()}
            />
          );
        },
      })}
      Confirm={({ context }) =>
        context.jobType === 'STUDENT' ? (
          <ConfirmStudent school={context.school} joinDate={context.joinDate} />
        ) : (
          <ConfirmEmployee company={context.company} joinDate={context.joinDate} />
        )
      }
    />
  );
}

declare function SelectJob(props: { onSelectSchool(): void; onSelectEmployee(): void }): JSX.Element;
declare function SelectSchool(props: { onNext(school: string): void }): JSX.Element;
declare function SelectEmployee(props: { onNext(company: string): void }): JSX.Element;
declare function EnterJoinDateBottomSheet(props: { onNext(joinDate: string): void; onClose(): void }): JSX.Element;
declare function ConfirmStudent(props: { school: string; joinDate: string }): JSX.Element;
declare function ConfirmEmployee(props: { company: string; joinDate: string }): JSX.Element;

Visit use-funnel.slash.page for docs, guides, API and more!

English | 한국어

Contributing

Read our Contributing Guide to familiarize yourself with @use-funnel development process, how to suggest bug fixes and improvements, and the steps for building and testing your changes.

Toss

MIT © Viva Republica, Inc. See LICENSE for details.