Files
Keyan ZhangandGitHub 8e202610a4 App Router: fix relative query/hash handling in next/link and router push/replace (#49521)
## Problem
Relative hash/query handling in `next/link` (e.g. `<Link
href="#hello">`) is broken in App Router, especially if you're on a
nested route.

This wasn't a problem in `/pages` because the href always get fully
resolved in `<NextLink>`; i.e. if you have `<Link href="#hash" />` on
`/hello`, it'll resolve the href to `/hello#hash` and use that
everywhere.

However, in App Router, `<Link>` no longer uses the current location to
resolve the href:
https://github.com/vercel/next.js/blob/5451564f364399003b05939fa6dd7d32c1dabec7/packages/next/src/client/link.tsx#L450-L457

Therefore navigating with `new URL(href, location.origin)` will skip the
current path and always apply the relative hash/query to the _root_
route:
https://github.com/vercel/next.js/blob/5451564f364399003b05939fa6dd7d32c1dabec7/packages/next/src/client/components/app-router.tsx#L208-L215

## Solution
Not 100% sure if this is the best solution, but since `app-router` is
already reading `window.location`, I'm using `location.href` as the base
URL to resolve the href.

I grep'd for `location.origin` and checked other callsites; seems like
only `app-router` deals with user specified hrefs.

Fixes https://github.com/vercel/next.js/issues/42157 &
https://github.com/vercel/next.js/issues/44139, and potentially
https://github.com/vercel/next.js/issues/48554 and
https://github.com/vercel/next.js/issues/22838

## Test Plan
```
pnpm testheadless test/e2e/app-dir/navigation
```

---------
2023-05-28 10:29:00 -07:00

21 lines
335 B
JavaScript

'use client'
import { useRouter } from 'next/navigation'
export function RouterPushButton() {
const router = useRouter()
return (
<h3 id="h3">
<button
id="button-to-h3-hash-only"
onClick={() => {
router.push('#h3')
}}
>
To #h3, hash only
</button>
</h3>
)
}