Skip to content

Instantly share code, notes, and snippets.

@malonehedges
Last active November 11, 2022 20:04
Show Gist options
  • Select an option

  • Save malonehedges/5c232a3bab049ff55d22374fe2889d35 to your computer and use it in GitHub Desktop.

Select an option

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.
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