vercel / vercel/next.js

Link does not scroll to anchor if it is within Suspense boundary

Open
#65,960 3 comments 13 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug Cache Components Linking and Navigating
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

  1. Open http://localhost:3000/
  2. Click on /products#category-42
  3. Observe <h2 id="category-42"> within the viewport (as expected)
  4. Go back to /
  5. Click on /products-with-suspense#category-42 (same page, but categories load inside Suspense boundary with a 100ms delay)
  6. 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

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.