mirror of
https://github.com/hanzoai/next.js.git
synced 2026-10-30 14:46:38 +00:00
Not 100% convinced that this is the correct fix but it's the best I can think of. Previously, we would sometimes call location.assign()/.replace() hundreds of times (or more) as I described in https://github.com/vercel/next.js/issues/48438 and https://github.com/vercel/next.js/issues/48309#issuecomment-1512290958. Sometimes this would just make things slow but the navigation would eventually succeed; sometimes this would just hang the browser. Now we trigger it only once (or—for a reason I don't quite understand—twice in dev, as you can see in the test) and never commit that render. This also fixes the bug I mentioned in https://github.com/vercel/next.js/issues/48438#issuecomment-1528649776 where usePathname() and useSearchParams() would return the page we are navigating to (even if that's an external page wholly unrelated to our site!). Fixes #48309, fixes #48438. link NEXT-1028 Co-authored-by: Jimmy Lai <[email protected]>
72 lines
2.0 KiB
JavaScript
72 lines
2.0 KiB
JavaScript
/*global navigation*/
|
|
'use client'
|
|
|
|
import { usePathname, useRouter, useSearchParams } from 'next/navigation'
|
|
import { useEffect, useTransition } from 'react'
|
|
|
|
let listening = false
|
|
let startedNavigating = false
|
|
|
|
export default function Page({ params: { storageKey } }) {
|
|
if (typeof window === 'undefined') {
|
|
throw new Error('Client render only')
|
|
}
|
|
|
|
let router = useRouter()
|
|
let path = usePathname()
|
|
let searchParams = useSearchParams().toString()
|
|
if (searchParams) {
|
|
path += `?${searchParams}`
|
|
}
|
|
|
|
// Log every pathname+searchParams we've seen
|
|
sessionStorage.setItem(`${storageKey}/path-${path}`, 'true')
|
|
|
|
let [isPending, startTransition] = useTransition()
|
|
useEffect(() => {
|
|
if (startedNavigating) {
|
|
sessionStorage.setItem(`${storageKey}/lastIsPending`, isPending)
|
|
}
|
|
})
|
|
|
|
// Read all matching logs and print them
|
|
let storage = Object.fromEntries(
|
|
Object.entries(sessionStorage).flatMap(([key, value]) =>
|
|
key.startsWith(`${storageKey}/`)
|
|
? [[key.slice(storageKey.length + 1), value]]
|
|
: []
|
|
)
|
|
)
|
|
|
|
return (
|
|
<>
|
|
<button
|
|
id="go"
|
|
onClick={() => {
|
|
// Count number of navigations triggered (in browsers that support it)
|
|
sessionStorage.setItem(
|
|
`${storageKey}/navigation-supported`,
|
|
typeof navigation !== 'undefined'
|
|
)
|
|
if (!listening && typeof navigation !== 'undefined') {
|
|
listening = true
|
|
navigation.addEventListener('navigate', (event) => {
|
|
let key = `${storageKey}/navigate-${event.destination.url}`
|
|
let count = +sessionStorage.getItem(key)
|
|
sessionStorage.setItem(key, count + 1)
|
|
})
|
|
}
|
|
|
|
startedNavigating = true
|
|
startTransition(() => {
|
|
router.push('https://example.vercel.sh/stuff?abc=123')
|
|
})
|
|
}}
|
|
>
|
|
go
|
|
</button>
|
|
<pre id="storage">{JSON.stringify(storage, null, 2)}</pre>
|
|
</>
|
|
)
|
|
}
|