Skip to content

Instantly share code, notes, and snippets.

@brunopk
Last active November 5, 2020 15:49
Show Gist options
  • Save brunopk/5577fafcc37c883cdb5bfdb761eca3a5 to your computer and use it in GitHub Desktop.
Save brunopk/5577fafcc37c883cdb5bfdb761eca3a5 to your computer and use it in GitHub Desktop.
Custom hook to query an arbitrary number of services asynchronously and parallelly using promises and async-await
import {useReducer, useEffect} from 'react';
const A_FETCH_INIT = 'FETCH_INIT';
const A_FETCH_SUCCESS = 'FETCH_SUCCESS';
const A_FETCH_FAILURE = 'FETCH_FAILURE';
const INITIAL_STATE = {
isLoading: false,
isError: false,
result: null,
};
/**
* Query a list of services asynchronously.
* @param {Function[]} service list of services (none of them receive params)
* @returns {Array} Returns an array with [isLoading, isError, result]
*
* - Initial values: [false, false, []]
* - isError returns false if one service fails.
* - isLoading will return true until all services completes
* - result is an array with same length as services array
*/
function useFetchParallel(services) {
const [state, dispatch] = useReducer((prevState, action) => {
switch (action.type) {
case A_FETCH_SUCCESS:
return {
...prevState,
isLoading: false,
result: action.data,
};
case A_FETCH_FAILURE:
return {
...prevState,
isError: true,
isLoading: false,
};
case A_FETCH_INIT:
return {
...prevState,
isLoading: true,
isError: false,
};
default:
return INITIAL_STATE;
}
}, INITIAL_STATE);
useEffect(() => {
const fetchData = async () => {
try {
dispatch({type: A_FETCH_INIT});
// One promise fail , all promise fail !
let res = await Promise.all(
services.map(
(s) =>
new Promise(async (resolve, reject) => {
try {
let r = await s();
resolve(r);
} catch (error) {
reject(error);
}
}),
),
);
dispatch({type: A_FETCH_SUCCESS, data: res});
} catch (error) {
console.log(error);
dispatch({type: A_FETCH_FAILURE});
}
};
if (state.result === null && !state.isLoading && !state.isError) {
fetchData();
}
}, [services, state.result, state.isLoading, state.isError]);
return [state.result, state.isLoading, state.isError];
}
export {useFetchParallel};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment