reactjsreact-routerredux-thunkreact-router-redux

redux-react-route v4/v5 push() is not working inside thunk action


In index.js push directly or throw dispatch works well:

...
import { push } from 'react-router-redux'

const browserHistory = createBrowserHistory()
export const store = createStore(
  rootReducer,
  applyMiddleware(thunkMiddleware, routerMiddleware(browserHistory))
)
// in v5 this line is deprecated
export const history = syncHistoryWithStore(browserHistory, store)

history.push('/any') // works well
store.dispatch(push('/any')) // works well

ReactDOM.render((
  <Provider store={store}>
    <Router history={history}>
      <App />
    </Router>
  </Provider>
), document.getElementById('root'))

App.js

class App extends Component {
  render() {
    return (
      <div className="app">
        <Switch>
          <Route path="/" component={Main} />
          <Route path="/any" component={Any} />
        </Switch>
      </div>
    );
  }
}
export default withRouter(connect(/*...*/)(App))

but in redux-thunk action all attempts ends by rewriting url, but without re-rendering

...
export function myAction(){
  return (dispatch) => {
    // fetch something and then I want to redirect...
    history.push('/any') // change url but not re-render
    dispatch(push('/any')) // change url but not re-render
    store.dispatch(push('/any')) // change url but not re-render
  }
}

This myAction is calling fetch() inside and should redirect after success.

If I run this.props.history.push('/any') inside component, it works! but I need to run redirect inside thunk action after successful fetch()

I was trying wrap all components with withRouter or Route, but didn't help.


Solution

  • Inject history object into your component and use push like this:

    import { withRouter } from 'react-router-dom'
    import { connect } from 'react-redux'
    
    @withRouter
    @connect(({auth})=>({auth}))
    class App extends Component {
    
      // on redux state change
      componentWillReceiveProps(nextProps) {
        if(!nextProps.auth)
          this.props.history.push('/login')
      }
    
      render() {
        return (
          <div>
            <Button
              // on button click
              onClick={this.props.history.push('/')}
            >
              Home page
            </Button>
          </div>
        );
      }
    }