react-router: Unexpected difference between clicking a or clicking the back button
Test Case
https://codesandbox.io/s/G6nWE3X0r
Steps to reproduce
- click on “page 1” link
- click on “back to home” link
- click on “page 2” link
- press the browser’s back button
Expected Behavior
It should go back to /.
Actual Behavior
It’s stuck showing “page 2”.
The <App> component is not blocking the update since it has the ‘location’ injected via the connect() function. However, if I change connect() to withRouter() it works.
Also, when I remove the <Switch> component the back button works as expected.
About this issue
- Original URL
- State: closed
- Created 7 years ago
- Reactions: 27
- Comments: 28 (9 by maintainers)
Commits related to this issue
- fix react-router-redux's race with react-router's context (https://github.com/ReactTraining/react-router/issues/5072) — committed to Bnei-Baruch/kmedia-mdb by yanivel 7 years ago
I think I was having this same problem and “solved” this for myself by connecting my switches to the store. Or you could pass the router location down through its props manually (since Switch allows you to pass in your own location object).
If you look in the React developer tools (at your switch component), you can actually see where the Switch component hangs up on the old location object without this hack.
@pshrmn I had created Projects for all of them, but they aren’t really that easy to use I’ve found. The labels work better.
@deiucanta That appears to be a side effect of using that site. I guess their browser emulation isn’t complete or to spec.
@timdorr this may be because of the
connectinApp.js. AddingwithRouteronfixes the issue. Example
This is also mentioned in https://github.com/ReactTraining/react-router/blob/master/packages/react-router/docs/guides/blocked-updates.md
and
https://reacttraining.com/react-router/core/guides/redux-integration/blocked-updates
FYI: I have been having the same issue but with react-router-redux v5 and react-router-dom. The suggestion from @pmwisdom to create a
ConnectedSwitchcontainer component and swapping this in place ofSwitchresolves the issue.@taurose Inspecting with ReactDevTools I can see that
<App>s location prop is changing when I hit the back button but inside the<Switch>it matches the previous route.The component structure is like this
On a regular location change, this is what happens
ConnectedRouterlistens to history and it dispatches a redux action to change the location in storeRouterlistens to history and updates the context valuesApplistens to the redux store and updates because there is a new locationSo, you’re basically saying that step 3 somehow happens before step 2 and when the
Routerupdates the context values is too late becauseAppwill not render again since the props don’t change.Am I right? Should this be fixed in the library or should I change my code to make it work?
@timdorr I initially got this behaviour working a project on my local machine and then I replicated it in codesandbox.io. Please reopen the issue and let me know if you have other hints on where the issue might be.
@pmwisdom Came to same solution as well. However, to me it feels like Switches wrapped in
ConnectedRoutershould do this on their own.@taurose Thanks for the investigation. This sounds like a legit bug with the library.
@deiucanta Sorry for the fast close. It’s still in alpha, so things like this need to be worked out.
I wonder if we should be creating the ConnectedSwitch everytime we want to provide a Switch in order to not to mess up with the connected location state or open up a pull request so React Router Redux can provide it’s own ConnectedSwitch…
Thanks @pmwisdom! I thought I was going nuts! I ended up using method 2, passing location directly to Switch.
It appeared to work ok, until in my case I realized that each route page was undergoing an FULL rerender on updates to the store for some strange reason, and this really wreaked havoc. Instead of connecting Switch, I ended up connecting each individual page component instead. Not ideal, but at least the rendering is working as expected now (efficient partial DOM updates).
Not sure if I have stuff setup wrong… wouldn’t be surprised…
I hit this too on a set of Routes outside a switch. So I guess it means a ConnectedRoute is needed if there isn’t a cleaner fix.
Just goes to show why context is not recommended by the react team!
I wonder if #5203 fixed this unintentionally…
Experiencing this as well.
Using ‘react-router-redux’, the
<ConnectedRouter>location state/prop is updating correctly as route changes. However, the location prop passed to the<Route>render methods are not updating in-sync. Example: after pressing the back button, the location.pathname has not been updated and will continue to be out of sync by one, such that when using<Route children={match}>you can see that match returns null, when the route does actually match.As previously mentioned, in the mean time passing down location from the connectedRouter as a prop to
<Route>,<Switch>etc will solve this problem.@deiucanta You can safely ignore this comment.
@timdorr I went ahead and made a
react-router-reduxlabel so that issues/PRs for it can be easily identified. If you don’t want this, feel free to remove it, but I thought that it could be helpful. Another label forreact-router-configcould probably also be made (and maybe the other packages as well).