Source:  Twitter logo

I'm using react-redux and react-router. I need to redirect after an action is dispatched.

For example: I have registration a few steps. And after action:

function registerStep1Success(object) {
    return {
        type: REGISTER_STEP1_SUCCESS,
        status: object.status
   };
}

I want to redirect to page with registrationStep2. How can I do this?

p.s. In history browser '/registrationStep2' has not been visited. This page appears only after successful result registrationStep1 page.

With React Router 2+, wherever you dispatch the action, you can call browserHistory.push() (or hashHistory.push() if that’s what you use):

import { browserHistory } from 'react-router'

// ...
this.props.dispatch(registerStep1Success())
browserHistory.push('/registrationStep2')

You can do this from async action creators too if that is what you use.

67 users liked answer #0dislike answer #067
Dan Abramov profile pic
Dan Abramov

Have you checked out react-router-redux? This library makes it possible to sync react-router with redux.

Here is an example from the documentation of how you can implement the redirection with a push action from react-router-redux.

import { routerMiddleware, push } from 'react-router-redux'

// Apply the middleware to the store
const middleware = routerMiddleware(browserHistory)
const store = createStore(
  reducers,
  applyMiddleware(middleware)
)

// Dispatch from anywhere like normal.
store.dispatch(push('/foo'))
26 users liked answer #1dislike answer #126
Eni Arinde profile pic
Eni Arinde

Simplest solution for router version 4+: We use "react-router-dom": "4.3.1" It doesn't work with version 5+

export your browser history from the place where it was initialised and use browserHistory.push('/pathToRedirect'):

Package history must be installed(example: "history": "4.7.2"):

npm install --save history

In my project I initialise browser history in index.js:

import { createBrowserHistory } from 'history';

export const browserHistory = createBrowserHistory();

Redirect in the action:

export const actionName = () => (dispatch) => {
    axios
            .post('URL', {body})
            .then(response => {
                // Process success code
                  dispatch(
                    {
                      type: ACTION_TYPE_NAME,
                      payload: payload
                    }
                  );
                }
            })
            .then(() => {
                browserHistory.push('/pathToRedirect')
            })
            .catch(err => {
                // Process error code
                    }
                );
            });
};
8 users liked answer #2dislike answer #28
Jackkobec profile pic
Jackkobec

To build on Eni Arinde previous answer's (I don't have the reputation to comment), here is how to use the store.dispatch method after an async action :

export function myAction(data) {
    return (dispatch) => {
        dispatch({
            type: ACTION_TYPE,
            data,
        }).then((response) => {
            dispatch(push('/my_url'));
        });
    };
}

The trick is to do it in the action files and not in the reducers, since reducers should not have side effects.

5 users liked answer #3dislike answer #35
Xalio08 profile pic
Xalio08

An updated answer using hooks; for router v5 users.

Working on react-router-dom:5.1.2.

No installation of external package is required.

import { useHistory } from "react-router-dom";

function HomeButton() {
  let history = useHistory();

  function handleClick() {
    history.push("/home");
  }

  return (
    <button type="button" onClick={handleClick}>
      Go home
    </button>
  );
}

You can use the history as you're previously used to.

More more details and APIs - read the manual

3 users liked answer #4dislike answer #43
YanivGK profile pic
YanivGK

We can use "connected-react-router".

    import axios from "axios";
    import { push } from "connected-react-router";
    
    export myFunction = () => {
      return async (dispatch) => {
        try {
          dispatch({ type: "GET_DATA_REQUEST" });
          const { data } = await axios.get("URL");
          dispatch({
            type: "GET_DATA_SUCCESS",
            payload: data
          });
        } catch (error) {
          dispatch({
            type: "GET_DATA_FAIL",
            payload: error,
          });
          dispatch(push("/notfound"));
        }
      };
    };

Attention-- Please go to https://github.com/supasate/connected-react-router read the docs and set up the connected-react-router first, and then use "push" from connected-react-router.

3 users liked answer #5dislike answer #53
Alex profile pic
Alex

You can use {withRouter} from 'react-router-dom'

Example below demonstrates a dispatch to push

export const registerUser = (userData, history) => {
  return dispatch => {
    axios
    .post('/api/users/register', userData)
    .then(response => history.push('/login'))
    .catch(err => dispatch(getErrors(err.response.data)));
  }
}

The history arguments is assigned to in the component as the a second parameter to the action creator (in this case 'registerUser')

2 users liked answer #6dislike answer #62
milesr profile pic
milesr

Here is the working copy of routing app

    import {history, config} from '../../utils'
        import React, { Component } from 'react'
        import { Provider } from 'react-redux'
        import { createStore, applyMiddleware } from 'redux'
        import Login from './components/Login/Login';
        import Home from './components/Home/Home';
        import reducers from './reducers'
        import thunk from 'redux-thunk'

        import {Router, Route} from 'react-router-dom'

        import { history } from './utils';

        const store = createStore(reducers, applyMiddleware(thunk))



        export default class App extends Component {
          constructor(props) {
            super(props);

            history.listen((location, action) => {
              // clear alert on location change
              //dispatch(alertActions.clear());
            });
          }
          render() {
            return (
              <Provider store={store}>
                <Router history={history}>
                  <div>
                    <Route exact path="/" component={Home} />
                    <Route path="/login" component={Login} />
                  </div>
                </Router>
              </Provider>
            );
          }
        }

export const config = {
    apiUrl: 'http://localhost:61439/api'
};
import { createBrowserHistory } from 'history';

    export const history = createBrowserHistory();
//index.js
export * from './config';
export * from './history';
export * from './Base64';
export * from './authHeader';

import { SHOW_LOADER, AUTH_LOGIN, AUTH_FAIL, ERROR, AuthConstants } from './action_types'

import Base64 from "../utils/Base64";

import axios from 'axios';
import {history, config, authHeader} from '../utils'
import axiosWithSecurityTokens from '../utils/setAuthToken'


export function SingIn(username, password){


    return async (dispatch) => {
      if(username == "gmail"){
        onSuccess({username:"Gmail"}, dispatch);
      }else{
      dispatch({type:SHOW_LOADER, payload:true})
        let auth = {
            headers: {
              Authorization: 'Bearer ' + Base64.btoa(username + ":" + password)
            }
          }
        const result = await axios.post(config.apiUrl + "/Auth/Authenticate", {}, auth);
        localStorage.setItem('user', result.data)
        onSuccess(result.data, dispatch);
    }
  }

}

export function GetUsers(){
  return async (dispatch) => {
var access_token = localStorage.getItem('userToken');
    axios.defaults.headers.common['Authorization'] = `Bearer ${access_token}` 

    var auth = {
      headers: authHeader()
    }
    debugger
      const result = await axios.get(config.apiUrl + "/Values", auth);
      onSuccess(result, dispatch);
      dispatch({type:AuthConstants.GETALL_REQUEST, payload:result.data})
  }
}



const onSuccess = (data, dispatch) => {

  const {username} = data;
  //console.log(response);
  if(username){
    dispatch({type:AuthConstants.LOGIN_SUCCESS, payload: {Username:username }});
    history.push('/');
    // Actions.DashboardPage();
  }else{
    dispatch({ type: AUTH_FAIL, payload: "Kullanici bilgileri bulunamadi" });
  }
  dispatch({ type: SHOW_LOADER, payload: false });
}
const onError = (err, dispatch) => {
  dispatch({ type: ERROR, payload: err.response.data });
  dispatch({ type: SHOW_LOADER, payload: false });
}

export const SingInWithGmail = () => {
  return { type :AuthConstants.LOGIN_SUCCESS}
}

export const SignOutGmail = () => {
  return { type :AuthConstants.LOGOUT}
}
0 users liked answer #7dislike answer #70
FERAMUZ MADENCİ profile pic
FERAMUZ MADENCİ
signup = e => {
  e.preventDefault();
  const { username, fullname, email, password } = e.target.elements,
    { dispatch, history } = this.props,
    payload = {
      username: username.value,
      //...<payload> details here
    };
  dispatch(userSignup(payload, history));
  // then in the actions use history.push('/<route>') after actions or promises resolved.
};

render() {
  return (
    <SignupForm onSubmit={this.signup} />
    //... more <jsx/>
  )
}
0 users liked answer #8dislike answer #80
isaadabbasi profile pic
isaadabbasi

while using react-router-dom version +5 you can't use useHistory hook in redux(redux toolkit).

So if you want to redirect after an action is dispatched you can get your history "via useHistory() hook" in your current page(component) then pass the history along with your payload as an argument to redux. Hence you can easily manage your history in redux after an action is dispatched like this : history.push ("somewhere)

0 users liked answer #9dislike answer #90
Amin Arshadinia profile pic
Amin Arshadinia

Copyright © 2022 QueryThreads

All content on Query Threads is licensed under the Creative Commons Attribution-ShareAlike 3.0 license (CC BY-SA 3.0).