-
-
Notifications
You must be signed in to change notification settings - Fork 10.8k
Stable callback fn passed as ref to a Link gets called twice on every re-render #12705
Copy link
Copy link
Open
Labels
Description
I'm using React Router as a...
library
Reproduction
- Render a
Linkinside a component and pass a stable callback function asref(e.gconsole.log). Feel free to do the same with a native element to see the normal behavior - Trigger a re-render in the parent component, e.g by increasing a counter state
https://codesandbox.io/p/sandbox/react-router-link-ref-repro-forked-dhm6sn
System Info
System:
OS: macOS 15.2
CPU: (12) arm64 Apple M3 Pro
Memory: 7.67 GB / 36.00 GB
Shell: 5.9 - /bin/zsh
Binaries:
Node: 20.17.0 - ~/.nvm/versions/node/v20.17.0/bin/node
npm: 10.8.2 - ~/.nvm/versions/node/v20.17.0/bin/npm
pnpm: 9.15.3 - ~/.nvm/versions/node/v20.17.0/bin/pnpm
Browsers:
Chrome: 131.0.6778.205
Edge: 131.0.2903.112
Safari: 18.2
npmPackages:
react-router: 7.1.1 => 7.1.1Used Package Manager
pnpm
Expected Behavior
The callback passed to the ref is only called when either the callback changes, or if the underlying node changes.
Actual Behavior
The callback gets called twice every time the Link is re-rendered, once with "null" and then with the actual anchor element. This can cause infinite re-renders in case the ref callback updates a state
This is probably because the refs are merged with a non-memoized mergeRefs function. Commonly that would be wrapped in a a useCallback.
react-router/packages/react-router/lib/dom/lib.tsx
Lines 644 to 645 in 7b04181
| ref={mergeRefs(forwardedRef, prefetchRef)} | |
| target={target} |
Reactions are currently unavailable