Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Link component leads to unnecessary re-renders with legacyBehavior #68596

Open
alex-statsig opened this issue Aug 6, 2024 · 0 comments
Open
Labels
bug Issue was opened via the bug report template. Navigation Related to Next.js linking (e.g., <Link>) and navigation. Performance Anything with regards to Next.js performance. Runtime Related to Node.js or Edge Runtime with Next.js.

Comments

@alex-statsig
Copy link

Link to the code that reproduces this issue

https://codesandbox.io/p/devbox/hardcore-neumann-dw8484

To Reproduce

Click the "Update Time" button, which updates a query parameter in the URL to the current time. Observe that the component "MyButton" re-renders due to the "Link" wrapper after a query param changed, despite its render being totally independent to changing query parameters and using React.memo

Current vs. Expected behavior

Current behavior is that the Link component uses useRouter() causing it to re-render when any query parameters change. This causes it to pass a new instance of the 'onClick', 'onMouseEnter', and 'onTouchStart' props to the child, which forces it to rerender.

Expected behavior is that the Link component should not need to re-render at all in this case, and even if it did re-render it should pass a stable function for onClick/onMouseEnter/onTouchStart to prevent the button from re-rendering (since only query params have changed, nothing related to the button's navigation has changed).

This causes many unnecessary re-renders across a website when navigations happen, in particular for components which remain mounted such as a header/left-rail or when only query parameters are changing (which doesn't impact most of the page typically).

Provide environment information

Operating System:
  Platform: linux
  Arch: x64
  Version: #1 SMP PREEMPT_DYNAMIC Sun Aug  6 20:05:33 UTC 2023
  Available memory (MB): 4102
  Available CPU cores: 2
Binaries:
  Node: 20.9.0
  npm: 9.8.1
  Yarn: 1.22.19
  pnpm: 8.10.2
Relevant Packages:
  next: 15.0.0-canary.104 // Latest available version is detected (15.0.0-canary.104).
  eslint-config-next: N/A
  react: 19.0.0-rc-06d0b89e-20240801
  react-dom: 19.0.0-rc-06d0b89e-20240801
  typescript: 5.3.3
Next.js Config:
  output: N/A

Which area(s) are affected? (Select all that apply)

Navigation, Performance, Runtime

Which stage(s) are affected? (Select all that apply)

next dev (local), next build (local), next start (local), Vercel (Deployed), Other (Deployed)

Additional context

I started a related discussion at #67520, but there was no traction there.

Also note that legacyBehavior is required for any custom button components (ex. using MUI or styled-components) and recommended in docs, so I don't think its valid to ignore

@alex-statsig alex-statsig added the bug Issue was opened via the bug report template. label Aug 6, 2024
@github-actions github-actions bot added Navigation Related to Next.js linking (e.g., <Link>) and navigation. Performance Anything with regards to Next.js performance. Runtime Related to Node.js or Edge Runtime with Next.js. labels Aug 6, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Issue was opened via the bug report template. Navigation Related to Next.js linking (e.g., <Link>) and navigation. Performance Anything with regards to Next.js performance. Runtime Related to Node.js or Edge Runtime with Next.js.
Projects
None yet
Development

No branches or pull requests

1 participant