Search code examples
javascriptreactjsaxiosredux-saga

How to re-throw the catched error in axios catch() block


In axios, why throw new Error() is not allowed inside catch()? I am in such requirement, where if an error is returned by the server, the catch block should throw an error, which later on will be handled by redux-saga and appropriate action would be dispatched.

The API call:

export const userSignupApi = userDetails => {
   const endpoint = `${URL_ROOT}${URN_SIGNUP}`;
    axios
    .post(endpoint, userDetails)
    .then(response => {
      console.log("Response: ", response);
      //do something with the response
    })
    .catch(error => {
      throw new Error(error.response.data.message);
    });
};

I am getting Unhandled Rejection (Error) because of the above catch block. Below is my saga which handles the operation:

import { call, takeLatest, put } from "redux-saga/effects";

function* handleUserSignup(action) {
  try {
    yield call(userSignupApi, action.userDetails);
    yield put(userSignupSuccess()); //dispatching success action
  } catch (error) {
    yield put(userSignupFail(error)); //dispatching error action
  }
}

function* watchUserSignup() {
  yield takeLatest(NEW_USER.SIGNUP, handleUserSignup);
}

Edit: Why I want the above code structure? Because this makes easy to unit test the API code and the saga code.


Solution

  • I got this working. I was doing it completely wrong. As suggested by @certianPerformance and after reading some questions and github issues, I got the right way to handle this. Instead of returning the api response, I should have returned the promise.
    Here is the solution:

    export const userSignupApi = userDetails => {
      const endpoint = `${URL_ROOT}${URN_SIGNUP}`;
    
      return axios.post(endpoint, userDetails);
    };
    

    Saga:

    import { call, takeLatest, put } from "redux-saga/effects";
    
    function* handleUserSignup(action) {
      try {
        const response = yield call(userSignupApi, action.userDetails);
        response.then(response => {
          const location = response.headers.location;
          put(userSignupSuccess(location));
          put(newUserWelcomeNote("Welcome user"));
        });
      } catch (error) {
        const errorMessage = error.response.data.message;
        yield put(userSignupFail(errorMessage));
      }
    }
    
    function* watchUserSignup() {
      yield takeLatest(NEW_USER.SIGNUP, handleUserSignup);
    }