connected-react-router: push a new route only triggers URL change but not location change

set up the connected-react-router as doc. but it only update the url rather than the location object when yield put(push(/somewhere)) in saga. so it won’t re-render the component.

try to resolve this via Update Blockingsection in react-router but it works fine outside the redux-saga. which means the push method from connected-react-router doesn’t work as expected.

any suggestions?

Thanks

About this issue

  • Original URL
  • State: open
  • Created 6 years ago
  • Reactions: 15
  • Comments: 49

Commits related to this issue

Most upvoted comments

Yeah that’s what I thought too, I felt like cheating; I’ve updated the codebox 😃

I was doing two things wrong :

  • Using two different instances of history
  • Using both ConnectedRouter and BrowserRouter

See if something is wrong with the codesandbox, but else, it’s ok for me 😃

I had the same problem and resolved it for some days. Finally, I found no history specified in tag <Router> and Router is BrowserRouter. I change it to <Router history={history}> (Router is default, not BrowserRouter) and the history is shared with router reducer. Code as below:

history.tsx

import { createBrowserHistory } from 'history';
export default createBrowserHistory();

store.tsx

import { routerMiddleware } from 'connected-react-router';

import history from './history';
import { createRootReducer } from './reducer';
const appRootReducer = createRootReducer(history);
const appRouterMiddleware = routerMiddleware(history);
//...

!App.tsx

//...
import { BrowserRouter as Router } from 'react-router-dom';
class AppComponent extends React.Component {
    render() {
        return (
              <Router>
                    <main>{renderRoutes(routes)}</main>
              </Router>
        );
    }
}

CHANGE TO:

//...
import { Router } from 'react-router-dom';

class AppComponent extends React.Component {
    render() {
        return (
              <Router history={history}>
                    <main>{renderRoutes(routes)}</main>
              </Router>
        );
    }
}
//...

I was using sagas to change the location. First I was using the push method from connected react router within a saga. I tried absolutely everything to make my route change. The URL would change but the component wouldn’t. I found removing the BrowserRouter component fixed my issue. Guessing it’s because I was using a switch and a browserRouter component.

<ConnectedRouter history={history}>
    <BrowserRouter> {/* Removing this component solved my issue. Possibly because it's using it's own history instance. I dunno. React + it's packages change too quickly for me to keep up and stay sane at the same time, given up caring... */}
      <Switch>
        <PrivateRouter exact path="/" component={App} />
        <Route exact path="/login" component={Login} />
        <Route component={NotFound} />
     </Switch>
   <BrowserRouter>
</ConnectedRouter>

I go it working when doing like this : https://codesandbox.io/s/p2wp49mmp0

I didn’t get that I should not use BrowserRouter. Thanks

For everyone looking for a quick (and probably dirty) fix using BrowserRouter … (at least it worked for me). BrowerRouter is a forceRefresh prop. You can set this true.

<BrowserRouter forceRefresh={true}></BrowserRouter

I have this same issue. I can confirm dispatching a push does not render anything. This is my component:

import React from "react";
import { connect } from "react-redux";
import { Switch, Route, Redirect, withRouter } from "react-router-dom";

import SideBar from "Components/SideBar";
import Dashboard from "Features/Dashboard";
import Team from "Features/Team";
import userActions from "store/user/actions";
import styles from "./styles.scss";

class AppRouter extends React.PureComponent {
    componentDidMount() {
        if (!this.props.hasUserDataLoaded) {
            this.props.loadUserData();
        }
    }

    render() {
        return (
            <div className={styles.container}>
                <SideBar pathname={this.props.location.pathname} />
                <Switch>
                    <Route path="/dashboard" Component={Dashboard} />
                    <Route path="/team" Component={Team} />
                    <Redirect to="/dashboard" />
                </Switch>
            </div>
        );
    }
}

const mapStateToProps = state => ({
    hasUserDataLoaded: state.user.hasUserDataLoaded,
});

const mapDispatchToProps = dispatch => ({
    loadUserData: () => dispatch(userActions.loadUserData()),
});

export default withRouter(connect(mapStateToProps, mapDispatchToProps)(AppRouter));

Make sure in component you are declare routes, wrapped with withRouter:

export default withRouter(
  connect(
    mapStateToProps,
    mapDispatchToProps,
  )(App),
);

Figured my issue out. Notice how I’ve used title case for the component prop in the Route. Double check your not doing something stupid like me 😃

Same is happening inside a saga, doing: yield put(push(‘/home’)) just changes the URL, but it does not render the component.

My config is the one from react-boilerplate plus this pr.

Using connected-react-router v6.4.0, If I don’t use a Switch then react-router doesn’t trigger the route. If I use Switch, I wasn’t getting any “Location_Change” events.

The solution for me was to put the Connected-Router inside the Switch

<Provider store={store}>
    <Switch>
      <ConnectedRouter history={history}>

Was having this issue. In case it may help someone, here’s what caused the issue for me:

First: Actions weren’t dispatching. Issue was that I was using BrowserRouter, I didn’t know about ConnectedRouter.

Second: Got actions to dispatch and URL would update, but the page wouldn’t change. Issue was that I needed to add the exact prop on every Route.

I solved it by removing:

yield take(LOCATION_CHANGE)
yield cancel(watcher)

And placing the watcher on app/containers/App/saga.js as I needed it to be global and persist through location changes.

p/s: Instead of removing it, you could use an other action to cancel it.

Hey, got the same issue here. The Links are working, but I can’t push new URL.

I have a working example here : https://codesandbox.io/s/vvznjm8mz3

Hello everyone, In case someone is struggling with this, none of the above worked for me. Finally I’ve reinstalled the packages and it started to work.

yarn remove react-router-dom @types/react-router-dom yarn add react-router-dom @types/react-router-dom

@fbove Thanks a lot man! It solved it to move saga to global scope! Thank you!

No everything looks good there. That’s the same setup as I have it.

Glad you got it working. 👍

If possible, can you check it once in redux-thunk? Is it working there? In my case also, it was not changing the location from redux-saga, so I just moved it in thunk. May be it doesn’t fit your use-case, but just have a try. Ex:

const mapDispatchToProps = dispatch => {
    dispatch(push(/somewhere/))
}