未验证 提交 76469219 编写于 作者: J Joe Haddad 提交者: GitHub

fix(router): consistent scroll behavior for Link/Router#push (#20606)

This pull request makes `Router#push` and `Router#replace` function identically to `<Link />`, i.e. reset scroll when the new render is complete.

Users can opt out of this new behavior via:
```tsx
const path = '/my-page'
router.push(path, path, { scroll: false })
```

---

Fixes #3249
上级 3246274d
......@@ -649,6 +649,12 @@ export default class Router implements BaseRouter {
window.location.href = url
return false
}
// Default to scroll reset behavior unless explicitly specified to be
// `false`! This makes the behavior between using `Router#push` and a
// `<Link />` consistent.
options.scroll = !!(options.scroll ?? true)
let localeChange = options.locale !== this.locale
if (process.env.__NEXT_I18N_SUPPORT) {
......
......@@ -101,7 +101,7 @@ describe('Build Output', () => {
expect(parseFloat(err404Size) - 3.7).toBeLessThanOrEqual(0)
expect(err404Size.endsWith('kB')).toBe(true)
expect(parseFloat(err404FirstLoad) - 65.2).toBeLessThanOrEqual(0)
expect(parseFloat(err404FirstLoad)).toBeCloseTo(65.3, 1)
expect(err404FirstLoad.endsWith('kB')).toBe(true)
expect(parseFloat(sharedByAll) - 61.8).toBeLessThanOrEqual(0)
......
import Link from 'next/link'
import { useRouter } from 'next/router'
import React from 'react'
const LongPageToSnapScroll = () => {
const router = useRouter()
return (
<div id="long-page-to-snap-scroll">
<Link href="#item-400">
......@@ -17,8 +19,28 @@ const LongPageToSnapScroll = () => {
})}
<Link href="/snap-scroll-position">
<a id="goto-snap-scroll-position">Go to snap scroll</a>
<a id="goto-snap-scroll-position">Go to snap scroll declarative</a>
</Link>
<div
id="goto-snap-scroll-position-imperative"
onClick={(e) => {
e.preventDefault()
router.push('/snap-scroll-position')
}}
>
Go to snap scroll imperative
</div>
<div
id="goto-snap-scroll-position-imperative-noscroll"
onClick={(e) => {
e.preventDefault()
router.push('/snap-scroll-position', '/snap-scroll-position', {
scroll: false,
})
}}
>
Go to snap scroll imperative (no scroll)
</div>
</div>
)
}
......
......@@ -445,7 +445,7 @@ describe('Client Navigation', () => {
})
describe('resets scroll at the correct time', () => {
it('should reset scroll before the new page runs its lifecycles', async () => {
it('should reset scroll before the new page runs its lifecycles (<Link />)', async () => {
let browser
try {
browser = await webdriver(
......@@ -478,6 +478,75 @@ describe('Client Navigation', () => {
}
}
})
it('should reset scroll before the new page runs its lifecycles (Router#push)', async () => {
let browser
try {
browser = await webdriver(
context.appPort,
'/nav/long-page-to-snap-scroll'
)
// Scrolls to item 400 on the page
await browser
.waitForElementByCss('#long-page-to-snap-scroll')
.elementByCss('#scroll-to-item-400')
.click()
const scrollPosition = await browser.eval('window.pageYOffset')
expect(scrollPosition).toBe(7208)
// Go to snap scroll page
await browser
.elementByCss('#goto-snap-scroll-position-imperative')
.click()
.waitForElementByCss('#scroll-pos-y')
const snappedScrollPosition = await browser.eval(
'document.getElementById("scroll-pos-y").innerText'
)
expect(snappedScrollPosition).toBe('0')
} finally {
if (browser) {
await browser.close()
}
}
})
it('should intentionally not reset scroll before the new page runs its lifecycles (Router#push)', async () => {
let browser
try {
browser = await webdriver(
context.appPort,
'/nav/long-page-to-snap-scroll'
)
// Scrolls to item 400 on the page
await browser
.waitForElementByCss('#long-page-to-snap-scroll')
.elementByCss('#scroll-to-item-400')
.click()
const scrollPosition = await browser.eval('window.pageYOffset')
expect(scrollPosition).toBe(7208)
// Go to snap scroll page
await browser
.elementByCss('#goto-snap-scroll-position-imperative-noscroll')
.click()
.waitForElementByCss('#scroll-pos-y')
const snappedScrollPosition = await browser.eval(
'document.getElementById("scroll-pos-y").innerText'
)
expect(snappedScrollPosition).not.toBe('0')
expect(Number(snappedScrollPosition)).toBeGreaterThanOrEqual(7208)
} finally {
if (browser) {
await browser.close()
}
}
})
})
describe('with hash changes', () => {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册