React-router: Router context updates incorrectly in response to browser-triggered navigation

Created on 22 Mar 2017  路  4Comments  路  Source: ReactTraining/react-router

Version

"react-router": "4.0.0",
"react-router-dom": "4.0.0"
"react-router-redux": "~5.0.0-alpha.4"

Test Case

See steps below

Steps to reproduce

  1. Use ConnectedRouter from react-router-redux:
// Currently at /stuff
<ConnectedRouter history={history} />
    <Router> // <== returned by <ConnectedRouter>
        <Switch>
            <Route exact path="/" component={A}/> // <== not rendered
            <Route path="/stuff" render={() => <Bundle />}>
                <Bundle> // <== Async bundle loader
                    <Connect(Layout)>
                        <Layout>
                            <Switch>
                                <Route [...stuff] component={BA} />
                                <Route [...stuff] component={BB} />
                                <Route [...stuff] component={BC} />
                            </Switch>
                        </Layout>
                    </Connect(Layout)>
                </Bundle>
            </Route>
            <Route path="/more" component={C}/> // <== not rendered
        </Switch>
    </Router>
</ConnectedRouter>
  1. Navigate around couple times with dispatch(push('/')), etc.
  2. Hit browser back / forward button couple times

Expected Behavior

Browser should render matched <Route> components

Actual Behavior

I checked my redux store, and all location states are reflected accurately. BUT, here's what happens:

  1. First back button click: URL changes in browser, but
  2. Second back or forward button click: URL changes in browser, and then
  3. Checking the devtool, I could see that context.router.history.location and context.router.route.location have different pathnames for the inner context.router.history.location had the correct location here. For the outer

Most helpful comment

All 4 comments

Strange - when I passed down props supplied by <Route path="/stuff" render={() => <Bundle />}> into the child of <Bundle> (i.e. <Connect(Layout) {...props} >), it worked. To be clear the props here are match, location, and history.

The connected component was already subscribed to location changes, and its own mapStateToProps was updating correctly. I'm not sure what exactly changed after passing down props mentioned above, but it fixed it.

So, how to fix this now? I am relying on redux-form, which is again relying on connect from redux. So I am not able to change this one...

@iDuuck It really depends on how you structured your component hierarchy. The problem with mine was that the <Bundle> component standing in between <Route> and <Connect()> prevented the updates by not passing props down from <Route> to <Connect()>. I've never used redux-form before, but if your decorated redux form is directly under a <Route> (e.g. <Route path='/path' component={MyForm} />), then I might try to experiment with how to make the wrapped MyForm component aware of <Route>'s changing props.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

misterwilliam picture misterwilliam  路  3Comments

andrewpillar picture andrewpillar  路  3Comments

Radivarig picture Radivarig  路  3Comments

wzup picture wzup  路  3Comments

alexyaseen picture alexyaseen  路  3Comments