Files
supabase/packages/ui-patterns/CommandMenu/api/hooks/useCrossCompatRouter.ts
Charis 1b89fa0b5c feat: command menu v2 ui components (#27761)
Co-authored-by: Francesco Sansalvadore <f.sansalvadore@gmail.com>
2024-07-16 14:14:03 -04:00

68 lines
1.8 KiB
TypeScript

'use client'
import { useRouter as useLegacyRouter } from 'next/compat/router'
import { useRouter as useNextRouter } from 'next/navigation'
import { useEffect, useMemo, useRef, useTransition } from 'react'
import { usePrevious } from 'react-use'
type Handler = (...evts: any[]) => void
function useHasChanged<T>(value: T, { onlyTo }: { onlyTo?: T } = {}) {
const prev = usePrevious(value)
if (prev === value) return false
if (onlyTo && value !== onlyTo) return false
return true
}
function useCrossCompatRouter() {
const legacyRouter = useLegacyRouter()
const newRouter = useNextRouter()
const isUsingLegacyRouting = !!legacyRouter
const [isPending, startTransition] = useTransition()
const hasPendingEnded = useHasChanged(isPending, { onlyTo: false })
const onPendingEnd = useRef(new Set<() => void>())
useEffect(() => {
if (!isUsingLegacyRouting && hasPendingEnded) {
onPendingEnd.current.forEach((fn) => fn())
}
}, [hasPendingEnded, isUsingLegacyRouting])
const api = useMemo(
() => ({
events: {
onRouteChangeComplete: (fn: Handler) => {
if (isUsingLegacyRouting) {
legacyRouter.events.on('routeChangeComplete', fn)
} else {
onPendingEnd.current.add(fn)
}
},
offRouteChangeComplete: (fn: Handler) => {
if (isUsingLegacyRouting) {
legacyRouter.events.off('routeChangeComplete', fn)
} else {
onPendingEnd.current.delete(fn)
}
},
},
push: (path: string) => {
if (isUsingLegacyRouting) {
legacyRouter.push(path)
} else {
startTransition(() => {
newRouter.push(path)
})
}
},
}),
[]
)
return api
}
export { useCrossCompatRouter }