Search code examples
react-reduxaxiosaction

Action with two chained requests. "Cannot read property then of undefined" error


Most of my api calls are a function that get called from an action like this

Action:

export const fetchSomethingAction = () => {
  return (dispatch) => {
    dispatch({ type: types.FETCH_SOMETHING_REQUEST })
    return api.fetchSomething()
      .then((response) => {
        dispatch({ type: types.FETCH_SOMETHING_SUCCESS, data: response.data })
      })
      .catch(error => {
        dispatch({ type: types.FETCH_SOMETHING_FAILURE, error })            
      })
  }
}

And the axios request goes something like this:

export const fetchSomething = () => {
  return axios({
    method: 'GET',
    url: `${api}/endpoint`
  });
}

Now I need to make two chained requests, and have the action dispatch an error if any of the two requests fails

So how do I chain the request to achieve this?

I was doing for example

export const fetchSomething = () => {
      axios({
        method: 'GET',
        url: `${api}/endpoint1`
      })
      .then(res => {
         return fetchSomething2(res.param)
      })
      .catch(err => return err)
    }

const fetchSomething2 = (param) => {
      return axios({
        method: 'GET',
        url: `${api}/endpoint1?param=${param}`
      });
    }

But I get Cannot read property 'then' of undefined in the action.

Do I need two actions, one for each function? Is that the proper way to do it? Thank you


Solution

  • Your fetchSomething function has an arrow function that is defined with braces, but does not have a return statement, and thus implicitly returns undefined. Change it to either not use braces, or have a return statement.

    Without braces:

    export const fetchSomething = () =>
          axios({
            method: 'GET',
            url: `${api}/endpoint1`
          })
          .then(res => {
             return fetchSomething2(res.param)
          })
          .catch(err => return err)
    

    With a return:

    export const fetchSomething = () => {
          return axios({
            method: 'GET',
            url: `${api}/endpoint1`
          })
          .then(res => {
             return fetchSomething2(res.param)
          })
          .catch(err => return err)
        }
    

    Here's a smaller example you can use to understand the difference:

    > a = () => 1; a()
    1
    
    > a = () => { 1 }; a()
    undefined
    
    > a = () => { return 1 }; a()
    1