Link does not scroll to anchor if it is within Suspense boundary
Nobody has claimed this yet.
- Dominant language
- JavaScript
- Stars
- 142k
- Forks
- 32.4k
- Avg merge
- 2d 14h
- Merged PRs (30d)
- 351
Description
Link to the code that reproduces this issue
https://github.com/kachkaev/next-link-scroll-with-suspense-mwe
To Reproduce
https://github.com/vercel/next.js/assets/608862/464a3373-1f35-4566-8da5-e0c2f6da0086
- Open http://localhost:3000/
- Click on
/products#category-42 - Observe
<h2 id="category-42">within the viewport (as expected) - Go back to
/ - Click on
/products-with-suspense#category-42(same page, but categories load inside Suspense boundary with a 100ms delay) - Observe the top of the page, unlike previously (unexpected)
Interestingly, navigating to /products-with-suspense#category-42 for the second time works correctly (i.e. it scrolls like /products#category-42). This is because of caching. When browser-side cache for /products-with-suspense expires, scrolling to anchor is skipped again.
Current vs. Expected behavior
I’d expect /products#category-42 and /products-with-suspense#category-42 to work the same way. If <h2 id="category-42"> shows while Suspense ‘islands’ get ‘resolved’, a user should be scrolled to the hash.
Perhaps, scrolling should be smooth in this case (otherwise, there will be a ‘flash’ of the top of the page and the transition to the anchor will be confusing). Alternatively, <Link> / router.push would not replace the old page until the #category-42 has appeared in the DOM or until all Suspense boundaries have been resolved. Either way, not observing any scrolling seems like a bug.
This bug can emerge as a regression after refactoring. Imagine we have a product catalog that has been working for years and we’ve added <Suspense> around the list of products to show page skeleton ASAP. Users will no longer be able to navigate to a specific category and this may remain unnoticed by devs without e2e tests.
Provide environment information
Operating System:
Platform: darwin
Arch: arm64
Version: Darwin Kernel Version 23.5.0: Wed May 1 20:12:58 PDT 2024; root:xnu-10063.121.3~5/RELEASE_ARM64_T6000
Available memory (MB): 32768
Available CPU cores: 10
Binaries:
Node: 20.11.1
npm: 10.5.0
Yarn: 4.0.0
pnpm: 8.10.5
Relevant Packages:
next: 14.3.0-canary.70 // Latest available version is detected (14.3.0-canary.70).
eslint-config-next: N/A
react: 19.0.0-beta-04b058868c-20240508
react-dom: 19.0.0-beta-04b058868c-20240508
typescript: 5.1.3
Next.js Config:
output: N/A
Which area(s) are affected? (Select all that apply)
Navigation, Partial Prerendering (PPR)
Which stage(s) are affected? (Select all that apply)
next dev (local), next start (local)
Additional context
No response
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the linked reproduction and trace Next.js navigation and hash-anchor scrolling when /products-with-suspense renders categories behind Suspense. Compare the first navigation with the cached second navigation; done means both routes reliably bring
into view, with regression coverage in the relevant test area.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript, nextjs, react
- Domain
- frontend, web-dev
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 55/100