Skip to content

Commit

Permalink
Fix shallow routing scroll (#21437)
Browse files Browse the repository at this point in the history
This ensures that Next.js will not scroll to the top of the page in shallow routing.

Fixes: #21386
Fixes: #21366
  • Loading branch information
kaykdm committed Jan 22, 2021
1 parent 74b6389 commit a5b0094
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 2 deletions.
5 changes: 4 additions & 1 deletion packages/next/next-server/lib/router/router.ts
Expand Up @@ -1093,13 +1093,16 @@ export default class Router implements BaseRouter {
!(routeInfo.Component as any).getInitialProps
}

// shallow routing is only allowed for same page URL changes.
const isValidShallowRoute = options.shallow && this.route === route
await this.set(
route,
pathname!,
query,
cleanedAs,
routeInfo,
forcedScroll || (options.scroll ? { x: 0, y: 0 } : null)
forcedScroll ||
(isValidShallowRoute || !options.scroll ? null : { x: 0, y: 0 })
).catch((e) => {
if (e.cancelled) error = error || e
else throw e
Expand Down
21 changes: 20 additions & 1 deletion test/integration/client-navigation/pages/nav/shallow-routing.js
Expand Up @@ -27,6 +27,17 @@ export default class extends Component {
Router.push(href, href, { shallow: true })
}

increaseNonShallow() {
const counter = this.getCurrentCounter()
const href = `/nav/shallow-routing?counter=${counter + 1}`
Router.push(href, href, {})
}

gotoNavShallow() {
const href = `/nav`
Router.push(href, href, { shallow: true })
}

render() {
return (
<div className="shallow-routing">
Expand All @@ -35,13 +46,21 @@ export default class extends Component {
Home
</a>
</Link>
<div id="counter">Counter: {this.getCurrentCounter()}</div>
<div id="counter" style={{ marginBottom: 4000 }}>
Counter: {this.getCurrentCounter()}
</div>
<div id="get-initial-props-run-count">
getInitialProps run count: {this.props.getInitialPropsRunCount}
</div>
<button id="increase" onClick={() => this.increase()}>
Increase
</button>
<button id="increase2" onClick={() => this.increaseNonShallow()}>
Increase Non-Shallow
</button>
<button id="invalidShallow" onClick={() => this.gotoNavShallow()}>
Invalid Shallow Nav
</button>
</div>
)
}
Expand Down
35 changes: 35 additions & 0 deletions test/integration/client-navigation/test/index.test.js
Expand Up @@ -854,6 +854,41 @@ describe('Client Navigation', () => {

await browser.close()
})

it('should keep the scroll position on shallow routing', async () => {
const browser = await webdriver(context.appPort, '/nav/shallow-routing')
await browser.eval(() =>
document.querySelector('#increase').scrollIntoView()
)
const scrollPosition = await browser.eval('window.pageYOffset')

expect(scrollPosition).toBeGreaterThan(3000)

await browser.elementByCss('#increase').click()
await waitFor(500)
const newScrollPosition = await browser.eval('window.pageYOffset')

expect(newScrollPosition).toBe(scrollPosition)

await browser.elementByCss('#increase2').click()
await waitFor(500)
const newScrollPosition2 = await browser.eval('window.pageYOffset')

expect(newScrollPosition2).toBe(0)

await browser.eval(() =>
document.querySelector('#invalidShallow').scrollIntoView()
)
const scrollPositionDown = await browser.eval('window.pageYOffset')

expect(scrollPositionDown).toBeGreaterThan(3000)

await browser.elementByCss('#invalidShallow').click()
await waitFor(500)
const newScrollPosition3 = await browser.eval('window.pageYOffset')

expect(newScrollPosition3).toBe(0)
})
})

describe('with URL objects', () => {
Expand Down

0 comments on commit a5b0094

Please sign in to comment.