react-router
react-router copied to clipboard
[Bug]: `useLocation` out of sync with `history.location`, leads to potential renders of unmatched `Route`s
What version of React Router are you using?
5.3.4 (but the same happens on v6)
Steps to Reproduce
Hey,
After upgrading to react@18, we started noticing unexpected renders of Routes that should no longer match. After some investigation we found that for a brief moment there's a discrepancy between what react-router thinks the pathname is, and what the browser thinks the pathname is. It looks like useLocation() and related are lagging behind createBrowserHistory().location as well as window.location - hence why I'm reporting this as a potential bug.
Our app is a rather old school React+Redux setup, and therefore relies heavily on navigation outside of the React context, primarily as a result of handling Redux actions - for example: dispatch an action -> perform http request -> redirect on complete. If the action performs a state update that the Route component subscribes to (such as a loading flag), it will do an extra render before unmounting, and during that render window.location.pathname will not match useLocation().pathname.
This was not happening in react@17. I ran the same experiment on react-router-dom@6 and got the same results. Unfortunately, it leads to some hard-to-find issues in code that for any reason relied on this behaviour, as well as some noticeable UX regressions where the additional render now causes unnecessary UI updates, and can delay the page transition.
See the links below that roughly simulate the setup that we have (excuse the occasional TS error). Open the browser console, then click the button and observe the console.logs:
react@17: https://stackblitz.com/edit/vitejs-vite-czwt3z?terminal=devreact@18: https://stackblitz.com/edit/vitejs-vite-werwvr?terminal=dev
Expected Behavior
useLocation().pathname and related should be consistent with createBrowserHistory().location.pathname as well as window.location.pathname. Routes that don't match should no longer render.
Actual Behavior
useLocation().pathname is stale compared to createBrowserHistory().location.pathname and window.location.pathname. Route component can render despite its path no longer matching.
Unfortunately, version 7 has the same issue