https://github.com/toss/use-funnel
A powerful and safe step-by-step state management library at React
https://github.com/toss/use-funnel
funnel react wizard-steps
Last synced: about 1 year ago
JSON representation
A powerful and safe step-by-step state management library at React
- Host: GitHub
- URL: https://github.com/toss/use-funnel
- Owner: toss
- License: mit
- Created: 2024-07-25T09:41:54.000Z (almost 2 years ago)
- Default Branch: main
- Last Pushed: 2025-05-12T05:50:09.000Z (about 1 year ago)
- Last Synced: 2025-05-12T06:36:32.953Z (about 1 year ago)
- Topics: funnel, react, wizard-steps
- Language: TypeScript
- Homepage: https://use-funnel.slash.page
- Size: 11.4 MB
- Stars: 384
- Watchers: 4
- Forks: 52
- Open Issues: 8
-
Metadata Files:
- Readme: README.md
- Contributing: CONTRIBUTING.md
- License: LICENSE
- Code of conduct: CODE_OF_CONDUCT.md
- Codeowners: .github/CODEOWNERS
Awesome Lists containing this project
README
# @use-funnel
[](https://github.com/toss/use-funnel/blob/main/LICENSE) [](https://discord.gg/vGXbVjP2nY)
`@use-funnel` is a [React Hook](https://react.dev/reference/rules/rules-of-hooks) 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
https://github.com/user-attachments/assets/8300d4ed-ab02-436e-a5a6-99c8d732e32f
```tsx
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 (
history.push('SelectSchool', { jobType: 'STUDENT' }),
selectEmployee: (_, { history }) => history.push('SelectEmployee', { jobType: 'EMPLOYEE' }),
},
render({ dispatch }) {
return (
dispatch('selectSchool')}
onSelectEmployee={() => dispatch('selectEmployee')}
/>
);
},
})}
SelectSchool={({ history }) => (
history.push('EnterJoinDate', (prev) => ({
...prev,
school,
}))
}
/>
)}
SelectEmployee={({ history }) => (
history.push('EnterJoinDate', (prev) => ({
...prev,
company,
}))
}
/>
)}
EnterJoinDate={funnel.Render.overlay({
render({ history, close }) {
return (
history.push('Confirm', { joinDate })}
onClose={() => close()}
/>
);
},
})}
Confirm={({ context }) =>
context.jobType === 'STUDENT' ? (
) : (
)
}
/>
);
}
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](https://use-funnel.slash.page) for docs, guides, API and more!
[English](https://use-funnel.slash.page/en) | [한국어](https://use-funnel.slash.page/ko)
## Contributing
Read our [Contributing Guide](./CONTRIBUTING.md) to familiarize yourself with `@use-funnel` development process, how to suggest bug fixes and improvements, and the steps for building and testing your changes.
MIT © Viva Republica, Inc. See [LICENSE](./LICENSE) for details.