Last active
November 11, 2022 20:04
-
-
Save malonehedges/5c232a3bab049ff55d22374fe2889d35 to your computer and use it in GitHub Desktop.
A hook to easily trap routing on a page for a Next.js app. Use this to prevent routing away from a page while you have pending changes or want to display some confirmation before routing.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import { useRouter } from 'next/router' | |
| import { useCallback, useEffect, useState } from 'react' | |
| /** | |
| * A hook that easily lets you add a route change trap. | |
| * @param shouldTrap Whether or not to trap the route change. | |
| * @returns An object with the following properties: | |
| * - `isTrapped`: Whether or not the route change is currently trapped. | |
| * - `leavePage`: A function that will leave the page. | |
| * - `stayOnPage`: A function that will stay on the page. | |
| */ | |
| export const useRouteTrap = ( | |
| shouldTrap: boolean, | |
| ): { | |
| isTrapped: boolean | |
| leavePage: () => void | |
| stayOnPage: () => void | |
| } => { | |
| const router = useRouter() | |
| const [desiredRoute, desiredRouteSet] = useState< | |
| { url: string; opts: { shallow: boolean } } | undefined | |
| >(undefined) | |
| useEffect(() => { | |
| const handleRouteChange = (url: string, opts: { shallow: boolean }) => { | |
| if (shouldTrap && desiredRoute === undefined) { | |
| desiredRouteSet({ url, opts }) | |
| router.events.emit('routeChangeError') | |
| throw 'routeChange aborted.' | |
| } | |
| } | |
| router.events.on('routeChangeStart', handleRouteChange) | |
| return () => { | |
| router.events.off('routeChangeStart', handleRouteChange) | |
| } | |
| }, [router, shouldTrap, desiredRoute]) | |
| const leavePage = useCallback(() => { | |
| if (desiredRoute !== undefined) { | |
| router.push(desiredRoute.url, undefined, desiredRoute.opts) | |
| } | |
| }, [desiredRoute, router]) | |
| const stayOnPage = useCallback(() => { | |
| desiredRouteSet(undefined) | |
| }, []) | |
| return { | |
| isTrapped: desiredRoute !== undefined, | |
| leavePage, | |
| stayOnPage, | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment