Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

reactjs axios interceptors how dispatch a logout action

Tags:

reactjs

axios

How can dispatch a logout action in case of status 401/403

with this code

import axios from "axios";
import { Storage } from "./utils/storage";
const instance = axios.create({
  baseURL: process.env.API_URL,
  timeout: 3000
});

const onRequestSuccess = config => {
  console.log("request success", config);
  const token = Storage.local.get("auth");
  if (token) {
    config.headers.Authorization = `Bearer ${token}`;
  }
  return config;
};
const onRequestFail = error => {
  console.log("request error", error);
  return Promise.reject(error);
};
instance.interceptors.request.use(onRequestSuccess, onRequestFail);

const onResponseSuccess = response => {
  console.log("response success", response);
  return response;
};
const onResponseFail = error => {
  console.log("response error", error);
  const status = error.status || error.response.status;
  if (status === 403 || status === 401) {
    //dispatch action logout
  }
  return Promise.reject(error);
};
instance.interceptors.response.use(onResponseSuccess, onResponseFail);

export default instance;

UPDATE

I peeped into the jhipster react code

and I saw

const actions = bindActionCreators({ logOut }, store.dispatch);
setupAxiosInterceptors(() => actions.logOut());

but I want to use the instance like

import axios from "../../../axios";
import API_URLS from "../../../constants/api";

const accountUrl = API_URLS.account;

const account = data => {
  return axios.post(accountUrl, data).then(response => {
    return response.data;
  });
};

export const Provider = {
  account
};

so I dont know which way to turn :(

WORK IT OUT WITH

Thanks to the help of Bruno Paulino I worked it out with this code

import axios from "./axios";
import { Storage } from "./utils/storage";

const setupAxiosInterceptors = onUnauthenticated => {
  const onRequestSuccess = config => {
    console.log("request success", config);
    const token = Storage.local.get("auth");
    if (token) {
      config.headers.Authorization = `${token.token}`;
    }
    return config;
  };
  const onRequestFail = error => {
    console.log("request error", error);
    return Promise.reject(error);
  };
  axios.interceptors.request.use(onRequestSuccess, onRequestFail);

  const onResponseSuccess = response => {
    console.log("response success", response);
    return response;
  };
  const onResponseFail = error => {
    console.log("response error", error);
    const status = error.status || error.response.status;
    if (status === 403 || status === 401) {
      onUnauthenticated();
    }
    return Promise.reject(error);
  };
  axios.interceptors.response.use(onResponseSuccess, onResponseFail);
};
export default setupAxiosInterceptors;


const {dispatch} = store;
setupAxiosInterceptors(()=>{
  dispatch(authLogout())
});
like image 936
Whisher Avatar asked Oct 23 '18 10:10

Whisher


2 Answers

You could include this interceptor code in the same place you have access to the redux store directly. Maybe in the file that you create your redux store (index.js)?

With that in place, you can dispatch the action directly from the redux store like that:

import reduxStore from './store';

import App from './components/App';

const router = (
  <Provider store={reduxStore}>
    <Router>
      <Route path="/" component={App}/>
    </Router>
  </Provider>
);

/** Intercept any unauthorized request.
* dispatch logout action accordingly **/
const UNAUTHORIZED = 401;
const {dispatch} = reduxStore; // direct access to redux store.
axios.interceptors.response.use(
  response => response,
  error => {
    const {status} = error.response;
    if (status === UNAUTHORIZED) {
      dispatch(userSignOut());
    }
   return Promise.reject(error);
 }
);

render(router, document.getElementById('app-root'));
like image 76
Bruno Paulino Avatar answered Nov 20 '22 06:11

Bruno Paulino


I got the same issue with you and this is my solution:

  1. Define axios interceptors and call redux store.
import Axios from 'axios';

const interceptor = (store) => {
    Axios.interceptors.request.use(
        (conf) => {
            if(!conf.headers['Authorization']){
                
            }
            console.log(store);
            debugger;
            // you can add some information before send it.
            // conf.headers['Auth'] = 'some token'
            return conf;
        },
        (error) => {
            debugger;
            return Promise.reject(error);
        }
    );
    Axios.interceptors.response.use(
        (next) => {
            debugger;
            return Promise.resolve(next);
        },
        (error) => {
            // You can handle error here and trigger warning message without get in the code inside
            
            debugger;
            return Promise.reject(error);
        }
    );
};
const store = createStore(reducer, enhancer);
interceptor(store);
  1. Config redux store into your project.
  2. Call axios request:
function getAllCompany(userObject) {

    let headers = { 'Authorization': 'Bearer ' + userObject.accessToken }

    return axios({
        method: 'post',
        url: rootURL + "/getallcompany",
        data: { },
        headers: headers
    }).then(handleResponse).catch(handleError);
}
like image 6
Robert Vo Avatar answered Nov 20 '22 08:11

Robert Vo