react-router: useRouterMatch returns new object on each render
Version
5.1.2
Test Case
https://codesandbox.io/s/eloquent-wave-vlixh
Steps to reproduce
CodeSanbox has a reproducible case
Expected Behavior
useRouteMatch hook returns a match object, when combined with a useEffect it is expected that the effect will run only when the window location or path parameters change
Actual Behavior
useRouteMatch hook returns a match object, when combined with a useEffect with the match as dependency the effect is triggered on every state change.
The codesandbox example performs a state update on a timeout and logs match whenever it is changed. The logs show that on every update match has changed even if the path has not. Memoizing the match object on window.location.pathname prevents this and has the expected behaviour
This line in the hook returns the result of matchPath which creates a new object every time it is executed.
Possible solution would be to do something like
return path ?
useMemo(() => matchPath(location.pathname, path), [location.pathname, path]) :
match
About this issue
- Original URL
- State: closed
- Created 5 years ago
- Reactions: 22
- Comments: 30 (7 by maintainers)
+1
The update is that I’ll be reviewing in the next week or two. This one is on the radar.
That’s now released in 6.1.0! 😃
Same for other hooks like
useParams. It triggers a rerender on every route change, even if there are no params in url. So basically using hooks = trigger app rerender on every route change.Maybe passing props you want to subscribe to into this hooks may help.
I face the same problem with
useRouteMatchtoday what is the status of this issue ?I think that makes sense. Can you submit a PR?
Is there any update on the PR? I can see all the check have passed, but there looks like no activity after April
I am still having this issue, is there a update on it?
I’ve opened up a PR to start a discussion on how this issue could be resolved in https://github.com/ReactTraining/react-router/pull/7822.
This is causing all kinds of unnecessary re-rendering, we’ve had to write our own set of wrapper functions to compensate
Nested routes trigger the infinite re-render loop. Would be great to memoize the hooks +1
If you want to perform side-effects on location change, then I think you can prob just rely on
location:Or I think you could make match stable in user land like this:
However, I don’t think using
React.useMemowould be safe unless you were merely trying to improve render performance as there’s no guarantee React won’t just throw away the memo’d value, e.g. don’t do this:A bit off topic, but simply using
useLocationinside a memo’ed component will cause a rerendering if any Route above the component rerenders: https://codesandbox.io/s/festive-greider-8did7The location value isn’t changed so it is trival to work-around, but quite a gothca IMO. https://github.com/facebook/react/issues/15156#issuecomment-474590693 for a related discussion.
@LoiKos Sorry, I have just noticed that my code was not complete. I was calling history.replace to reset the location state.
So I have updated my code. @LoiKos Can you managed to reproduce the infinite loop ?