6
\$\begingroup\$

I am developing an application where there are lots of async actions. I wanted to go with redux-saga but most have insisted to continue with redux-thunk. In redux-thunk, inside each action we have to work with async operation using then, dispatch, catch, etc. This makes looks actions so messy and lots of code will be repeated. I wanted to create a generic dataLoader for the use of redux-thunk and axios.

Here is my attempt:

export class Company {
/**
* Generic api data loader
*/
static dataLoader(apiUri, onSuccess, onError, data, ...actionArguments) {
 const requestURL = `${API_BASE}${apiuri}`;
 try {
 let options;
 if (data !== undefined) {
 // if we have data to post
 options = {
 method: 'POST',
 url: requestURL,
 body: JSON.stringify(data),
 headers: {
 'Content-Type': 'application/json',
 'X-Requested-With': 'XMLHttpRequest',
 },
 };
 }
 }
 return function(dispatch) {
 axios(options)
 .then(response => {
 dispatch({
 type: onSucess,
 payload: response.data
 });
 })
 .catch(error => {
 dispatch({ type: onError, payload: err});
 });
 }
}
static get(apiUri, onSuccess, onError, ...actionArguments) {
 return this.dataLoader(apiUri, onSuccess, onError, undefined, ...actionArguments);
 }
 /*
 * Shorthand POST function
 */
 static post(apiUri, onSuccess, onError, data, ...actionArguments) {
 return this.dataLoader(apiUri, onSuccess, onError, data, ...actionArguments);
 }
}

I want to convert the following code to further this one:

export function showResultofApartment() {
 return (dispatch) => {
 dispatch({ type: 'APARTMENT_FETCH_START' });
 const token = localStorage.getItem('token');
 return axios.get(`${API_URL}/newoffers/apartment/`)
 .then((response) => {
 console.log('response apart', response.data);
 dispatch({ type: 'APARTMENT_FETCH_SUCCESS', payload: response.data });
 })
 .catch((err) => {
 dispatch({ type: 'APARTMENT_FETCH_FAILURE', payload: err });
 });
 };
}

to such or more efficient than this:

export function showResultofApartment() {
 return(dispatch) => {
 dispatch({ type: APARTMENT_FETCH_START });
 const token = localStorage.getItem('token');
 return Company.get('/apartments', APARTMENT_FETCH_SUCCESS, APARTMENT_FETCH_ERROR);
 // if post then Company.post('/apartment', APARTMENT_POST_SUCCESS, APARTMENT_POST_ERROR, data)
 }
}

I have not tested this. I am just throwing my idea through code to get other experts idea on how I should handle such case for a more efficient technique without using other more external libraries.

Jamal
35.2k13 gold badges134 silver badges238 bronze badges
asked May 31, 2017 at 2:31
\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

This is one of the problems with async actions in redux-thunk. As you point out you have to create constants for "APARTMENT_FETCH_STATUS" and manually dispatch actions of this type before and after the request has been done.

The redux-promise-middleware library actually does all this for you. You simply create an action like so:

const foo = () => ({
 type: 'FOO',
 payload: new Promise()
});

and the library will take care of dispatching an action of type "FOO_PENDING", and then of type "FOO_FULFILLED" when the promise has resolved. With redux-promise-middleware your actions would become something like this:

const showResultOfApartment = () => ({
 type: "FETCH_APARTMENT",
 payload: axios.get("http://api.com/apartments").then(result => result.data)
})

In your reducer you would create handlers for "FETCH_APARTMENT_PENDING", "FETCH_APARTMENT_FULFILLED" and "FETCH_APARTMENT_REJECTED". In the case where the promise fulfills or rejects, you also get the result of the promise by accessing action.payload. An example of what it could look like:

function apartmentReducer(state, action){
 if(action.type === "FETCH_APARTMENT_PENDING"){
 return Object.assign({}, state, { loading: true })
 }
 else if(action.type === "FETCH_APARTMENT_FULFILLED"){
 return Object.assign({}, state, { loading: false, apartment: action.payload })
 }
 else if(action.type === "FETCH_APARTMENT_REJECTED"){
 return Object.assign({}, state, { loading: false, error: action.payload })
 }
 return state;
}

redux-promise-middleware

Introduction to redux-promise-middleware

answered May 31, 2017 at 18:58
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.