-
Notifications
You must be signed in to change notification settings - Fork 27.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix inconsistent scroll restoration behavior (#59366)
### What? While scrolled on a page, and when following a link to a new page and clicking the browser back button or using `router.back()`, the scroll position would sometimes restore scroll to the incorrect spot (in the case of the test added in this PR, it'd scroll you back to the top of the list) ### Why? The refactor in #56497 changed the way router actions are processed: specifically, all actions were assumed to be async, even if they could be handled synchronously. For most actions this is fine, as most are currently async. However, `ACTION_RESTORE` (triggered when the `popstate` event occurs) isn't async, and introducing a small amount of delay in the handling of this action can cause the browser to not properly restore the scroll position ### How? This special-cases `ACTION_RESTORE` to synchronously process the action and call `setState` when it's received, rather than creating a promise. To consistently reproduce this behavior, I added an option to our browser interface that'll allow us to programmatically trigger a CPU slowdown. h/t to @alvarlagerlof for isolating the offending commit and sharing a minimal reproduction. Closes NEXT-1819 Likely addresses #58899 but the reproduction was too complex to verify.
- Loading branch information
Showing
9 changed files
with
151 additions
and
16 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
10 changes: 10 additions & 0 deletions
10
test/e2e/app-dir/navigation/app/scroll-restoration/context.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import { createContext } from 'react' | ||
|
||
export interface Item { | ||
id: number | ||
} | ||
|
||
export const ItemsContext = createContext<{ | ||
items: Item[] | ||
loadMoreItems: () => void | ||
}>({ items: [], loadMoreItems: () => {} }) |
27 changes: 27 additions & 0 deletions
27
test/e2e/app-dir/navigation/app/scroll-restoration/layout.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
'use client' | ||
import { useState } from 'react' | ||
import { ItemsContext, type Item } from './context' | ||
|
||
const createItems = (start: number, end: number): Item[] => { | ||
const items: Item[] = [] | ||
for (let i = start; i <= end; i++) { | ||
items.push({ id: i }) | ||
} | ||
return items | ||
} | ||
|
||
export default function Layout({ children }: { children: React.ReactNode }) { | ||
const [items, setItems] = useState<Item[]>(createItems(1, 50)) | ||
|
||
const loadMoreItems = () => { | ||
const start = items.length + 1 | ||
const end = start + 50 - 1 | ||
setItems((prevItems) => [...prevItems, ...createItems(start, end)]) | ||
} | ||
|
||
return ( | ||
<ItemsContext.Provider value={{ items, loadMoreItems }}> | ||
{children} | ||
</ItemsContext.Provider> | ||
) | ||
} |
13 changes: 13 additions & 0 deletions
13
test/e2e/app-dir/navigation/app/scroll-restoration/other/page.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
'use client' | ||
import { useRouter } from 'next/navigation' | ||
|
||
export default function Page() { | ||
const router = useRouter() | ||
return ( | ||
<div> | ||
<button onClick={() => router.back()} id="back-button"> | ||
Go Back | ||
</button> | ||
</div> | ||
) | ||
} |
23 changes: 23 additions & 0 deletions
23
test/e2e/app-dir/navigation/app/scroll-restoration/page.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
'use client' | ||
import Link from 'next/link' | ||
import React, { useContext } from 'react' | ||
import { ItemsContext } from './context' | ||
|
||
export default function Page() { | ||
const { items, loadMoreItems } = useContext(ItemsContext) | ||
|
||
return ( | ||
<div> | ||
<h1>Page</h1> | ||
<ul> | ||
{items.map((item) => ( | ||
<li key={item.id}>Item {item.id}</li> | ||
))} | ||
</ul> | ||
<button id="load-more" onClick={loadMoreItems}> | ||
Load More | ||
</button> | ||
<Link href="/scroll-restoration/other">Go to Other</Link> | ||
</div> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters