0
votes

I'm writing a function to send API requests. When I get the response from that API I want to dispatch redux action if the user has called my function in dispatch or just do nothing if not. I'm using redux thunk.

Right now I've written two separate methods for this.

  1. This does not dispatch after getting the response from the API, just return the Promise.
const getAnimalsList = () => return axios.request({url: 'api.domain.com/animals'});

This function will be called as usual functions.


  1. It dispatches an action something after getting a response from the API
const getAnimalsList = () => (dispatch, getState) => {
    axios.request({url: 'api.domain.com/animals'}).then(
        res => dispatch({type: 'RESPONSE RECEIVED', data: res}),
        err => dispatch({type: 'ERROR', err})
    );
}

This function will be called inside dispatch as dispatch(getAnimalsList())


Now what I want is to know in a single function whether it was called inside the dispatch or just called normally.

example:

const getAnimalsLis = () => {
    let prom = axios.reques({url: 'api.domain.com/animals});
    if(function_is_called_inside_dispatch){
        return dispatch => {
            prom.then(
                res => dispatch({type: 'RESPONSE RECEIVED', data: res}),
                err => dispatch({type: 'ERROR', err})

            );
        }
    }
    else return prom;

}
2

2 Answers

0
votes

This is a wrong way to do things. There's no way to detect that the function was called like dispatch(getAnimalsList()) or just getAnimalsList(). Due to operator precedence, it has already been called as getAnimalsList() when an action provided to dispatch. The only way would be to call it differently, dispatch(getAnimalsList(CALLED_AS_AN_ACTION)).

A correct way is to not mix functions that serve different purposes. The code can be made DRYer than it is, getAnimalsList function already contains common code that could be extracted otherwise:

const getAnimalsList = () => return axios.request({url: 'api.domain.com/animals'});

const getAnimalsListAction = () => (dispatch, getState) => {
    return getAnimalsList().then(
        res => dispatch({type: 'RESPONSE RECEIVED', data: res}),
        err => dispatch({type: 'ERROR', err})
    );
}
0
votes

Please do not define getState if you are not planning on using it:

const getAnimalsList = () => (dispatch, getState) => {
    axios.request({url: 'api.domain.com/animals'}).then(
        res => dispatch({type: 'RESPONSE RECEIVED', data: res}),
        err => dispatch({type: 'ERROR', err})
    );
}

And also use the async/await syntax, its more explicit for you as to what is going on:

export const getAnimalsList = () => async dispatch => {
  const response = await jsonAnimals.get("/animals");
  dispatch({ type: "RESPONSE_RECEIVED", payload: response.data });
};

Then create a folder/file system like so: apis/jsonAnimals.js:

Place your Axios code in there:

import axios from 'axios';

export default axios.create({
    baseURL: 'http://api.domain.com'
});

Okay, now you have a nice clean Redux application, makes it easier on the eyes, easier to debug.

Now if you want to test it in the console then you could do

export const testGetAnimalsList = () => async (dispatch, getState) => {
  await dispatch(getAnimalsList());
  console.log(getState().animals);
};

export const getAnimalsList = () => async dispatch => {
  const response = await jsonAnimals.get("/animals");
  dispatch({ type: "RESPONSE_RECEIVED", payload: response.data });
};