16

I'm using axios in my react/redux application and when I get errors like 401, 404, etc I currently have to deal with them for each action function when I make the calls to axios. I have a axios_config.js where I've wrapped the axios calls with some common idioms. For example:

// need to move this to app config
const BASE_URL = 'http://localhost:8080/api/';

function config() {
  return {
    headers: {'X-Token-Auth': localStorage.getItem('token')}
  }
}

export function fetchData(url) {
  return axios.get(`${BASE_URL}${url}`, config());
};

Where I'm struggling are the common errors like 401, 404, etc. Currently, I'm doing this:

export function fetchBrands() {
  return function(dispatch) {
    dispatch({type:FETCHING_BRANDS});

    fetchData('brands')
      .then(response => {
        dispatch({
          type: FETCH_BRANDS_SUCCESS,
          payload: response
        });
      })
      .catch(err => {
        // deal with errors
      });
  }
}

But in the catch block, I don't want to have to deal with 401, 404 etc every single time. So I need to be able to deal with those on a more global scale but still have the ability to handle specific errors to the request like server side validation errors for example.

Gregg
  • 34,973
  • 19
  • 109
  • 214

2 Answers2

37

You can use response interceptors as documents in axios documentation.

axios.interceptors.response.use(undefined, function (error) {
    if(error.response.status === 401) {
      ipcRenderer.send('response-unauthenticated');
      return Promise.reject(error);
    }
  });

other thread with same discussion

Leniel Maccaferri
  • 100,159
  • 46
  • 371
  • 480
prasann shah
  • 381
  • 3
  • 4
4

You can try to write a function that accepts a function and returns the function with a catch attached. You can even pass an optional secondary argument to execute local catch logic.

This could then be moved to a single file and you can always modify it there.

export function fetchBrand(id) {
  return function (dispatch) {
    wrapCatch(
      fetchData(`brands/${id}`)
        .then(response => {
          dispatch({
            type: FETCH_BRAND_SUCCESS,
            payload: response
          });
        }),
      function (err) {
        // deal with errors
      }
    );
  }
}
  
export function wrapCatch(f, localErrors) {
  return f.catch(err => {
      // deal with errors
      localErrors();
  });
}

Hope this helps.

Gregg
  • 34,973
  • 19
  • 109
  • 214
link
  • 2,480
  • 1
  • 16
  • 18
  • Thanks, I'll give this a shot today and see how it works out. – Gregg Oct 14 '16 at 13:19
  • I made some edits because your code wasn't quite right, but the gist is good enough. Marked as the right answer because it does solve the problem, however, I kind of feel like theirs a slightly more elegant way of handling this. Still requires the end user to understand too much about the error handling. – Gregg Oct 14 '16 at 15:01
  • @link to make you are not passing a function here, but rather the request object. Function seems to be misleading here. – Aftab Naveed May 23 '17 at 10:43