How redirect user if error.status == 401?

Viewed 2061

My goal is to redirect users if the code of request is equal to 401. I wrote follow code but it display me error 401. It displays me 401 (from console.log but below error). How can I implement redirection, if the error is equal to 401?

import axiosConfig from "../../config/axios";
import actions from "./actions";
import { Redirect } from "react-router";
const fetchUser = async () => {
    const response = await axiosConfig.get('api/get-user')
        .catch(function (error) {
            console.log(error.response.status) // 401
            console.log(error.response.data.error) //Please Authenticate or whatever returned from server
            if (error.response.status == 401) {
                return(
                    <Redirect
                        to={{
                            pathname: '/login',
                            state: { from: location },
                        }}
                    />
                );
            }
        });
    return response.data
}
export const getUser = () =>
    async (dispatch) => {
        const user = await fetchUser()
       dispatch(actions.setUser(user));
    }

@Update Routing setup

const Container = () => {
    return (
        <div className="container">
                            <Router>
                                <Switch>
                                    <Route path="/login">
                                        <Login />
                                    </Route>
                                    <Route path="/register">
                                        <Login />
                                    </Route>
                                        <Route path="/all-users">
                                            <Alltasks />
                                        </Route>
                                        <Route path="/all-articles">
                                            <AllUsers />
                                        </Route>
                                </Switch>
                            </Router>
                            <ToastContainer />
        </div>
    );
}
1 Answers

You can't return a Redirect component from an action, utility, or callback like this and expect it to be rendered and effect a redirect to a new route. Your option is to access the history object and invoke an imperative redirect.

Option 1

Connect your router to redux with connected-react-router. The basic gist is to create a custom "createRootReducer" function, create a history object, use the "ConnectedRouter" component. This allows you to dispatch redux actions to effect navigation actions in your app.

Follow the steps to setup and connect routing to your redux store.

To use in your asynchronous action:

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

...

const fetchUser = async () => {
  try {
    const response = await axiosConfig.get('api/get-user');
    return response.data;
  } catch (error) {
    if (error.response.status == 401) {
      throw new Error(error);
    }
  }
}

export const getUser = () => async (dispatch) => {
  try {
    const user = await fetchUser();
    dispatch(actions.setUser(user));
  } catch {
    dispatch(replace('/login'));
  }
}

Option 2

Create a history object and import and use in getUser action.

Create a memory, hash, or browser history object:

import { createBrowserHistory } from 'history';

export const history = new createBrowserHistory();

Import the plain Router from react-router and pass the history object as prop:

import { Router } from 'react-router';
import { history } from '../path/to/custom/history';

...

<Router history={history}>
  ...
</Router>

Import and use history in the getUser action:

import { history } from '../path/to/custom/history';

...

const fetchUser = async () => {
  try {
    const response = await axiosConfig.get('api/get-user');
    return response.data;
  } catch (error) {
    if (error.response.status == 401) {
      throw new Error(error);
    }
  }
}

export const getUser = () => async (dispatch) => {
  try {
    const user = await fetchUser();
    dispatch(actions.setUser(user));
  } catch {
    history.replace('/login');
  }
}

Option 3

Pass the history object to the getUser action.

const fetchUser = async () => {
  try {
    const response = await axiosConfig.get('api/get-user');
    return response.data;
  } catch (error) {
    if (error.response.status == 401) {
      throw new Error(error);
    }
  }
}

export const getUser = (history) => async (dispatch) => {
  try {
    const user = await fetchUser();
    dispatch(actions.setUser(user));
  } catch {
    history.replace('/login');
  }
}

Usage:

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

...

const history = useHistory();

...

getUser(history);

...

const mapDispatchToProps = {
  getUser,
};
Related