Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

react-axios-middleware promise handling

I am working on a React application which uses redux-axios-middleware to do XHR requests. The way it is setup is with a client in the index.js like so:

const client = axios.create({ //all axios can be used, shown in axios documentation
  baseURL:'https://api.vktest.xxx/api',
  responseType: 'json',
  validateStatus: function (status) {
    return status >= 200 && status < 300
  }
});

const axiosMiddle = axiosMiddleware(client)

export const store = createStore(rootReducer, composeEnhancers(applyMiddleware(thunk, axiosMiddle)))

From my component I am then calling my action like so:

store.dispatch(loginAction(credentials))

This is the action:

import { LOGIN } from './types'

export function loginAction(credentials) {

  return dispatch => {
      return dispatch(doLogin(credentials) ).then(
      response => {
        dispatch({type: 'LOGIN_SUCCESS', response})
      },
      error => {
        dispatch({type: 'LOGIN_FAIL', error})
        throw error
      }
    )
  }
}

function doLogin(credentials) {
  return {
    type: LOGIN,
    payload: {
      request: {
        url: '/login/',
        method: 'POST',
        data: {
          username: credentials.username,
          password: credentials.password
        }
      }
    }
  }
}

It dispatches the doLogin function which is captured by axios-middleware to do the XHR call. After the call the axios promise contains either the type LOGIN_SUCCESS or LOGIN_FAIL. Axios automatically dispatches these types and the reducers can act on them. So far so good.

However (and I am trying to be as clear as possible), when the axios request fails, the axios promise is rejected and the LOGIN_FAIL type is dispatched. Since that promise is resolved the .then(..).catch(..) block is alway's calling the .then. I cannot seem to handle the axios error with doing something ugly in the .then block which handles the dispatch callback and not the axios callback.

To clearify the following is happening:

store.dispatch -> action -> doLogin -> axios -> reducer -> back to action dispatch.

I want to handle XHR errors between the axios and reducer step but when I do:

import { LOGIN } from './types'

export function loginAction(credentials) {

  return dispatch => {
      return dispatch(doLogin(credentials).then(
      response => {
        dispatch({type: 'LOGIN_SUCCESS', response})
      },
      error => {
        dispatch({type: 'LOGIN_FAIL', error})
        throw error
      }
    ))
  }
}

function doLogin(credentials) {
  return {
    type: LOGIN,
    payload: {
      request: {
        url: '/login/',
        method: 'POST',
        data: {
          username: credentials.username,
          password: credentials.password
        }
      }
    }
  }
}

I get the following error:

Uncaught TypeError: doLogin(...).then is not a function
    at authentication.js:6

The reason I want to fix this is because the current setup dispatches the following:

Current flow

As seen in the image both the LOGIN_FAIL (axios) and the LOGIN_SUCCESS (dispatch) are being called. I want to be able to handle the axios error myself since I want to be able to for example give the user feedback of a failed login attempt. Somehow I am not able to figure out how.

Can someone help me?

like image 555
nobody Avatar asked Oct 17 '22 06:10

nobody


1 Answers

I think I know what you mean.

You can change that behavior by setting returnRejectedPromiseOnError in middleware config.

Note that promise is returned only to chain actions. If you set this option you will have to always apply catch callback or you will be getting unhandled rejection when calling Promise errors. And this might be causing some issues when handled in components, because these callbacks may be fired when component is already unmounted.

Im my code I try to avoid then as much as possible to avoid these side effects but when I have to I do it like:

fetchSomething.then(action => {
  if(action.type.endsWith('SUCCESS')) {
      ....
  }

})
like image 70
Tomasz Mularczyk Avatar answered Oct 21 '22 07:10

Tomasz Mularczyk