Last active
November 5, 2020 15:46
-
-
Save brunopk/0812bbfc7925e58da34aab3ad67646b4 to your computer and use it in GitHub Desktop.
Custom hook to query an arbitrary number of services asynchronously and serially
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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[]} services list of services (array of length n) | |
* @param {Object[]} params params for services (array of length n) | |
* @returns {Array} Returns an array with [result, isLoading, isError] | |
* | |
* - Initial values: [false, false, []] | |
* - isError is false if one service fails. | |
* - isLoading will return true until all services completes | |
* - result is an array of length n | |
*/ | |
function useFetchSerial(services, params) { | |
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); | |
if (typeof params === 'undefined') { | |
params = services.map((s) => null); | |
} | |
useEffect(() => { | |
const fetchData = async () => { | |
try { | |
dispatch({type: A_FETCH_INIT}); | |
let res = []; | |
for (let i = 0; i < services.length; i++) { | |
let r = await services[i](params[i]); | |
res.push(r); | |
} | |
dispatch({type: A_FETCH_SUCCESS, data: res}); | |
} catch (error) { | |
dispatch({type: A_FETCH_FAILURE}); | |
} | |
}; | |
if (state.result === null && !state.isLoading && !state.isError) { | |
fetchData(); | |
} | |
}, [services, params, state.result, state.isError, state.isLoading]); | |
return [state.result, state.isLoading, state.isError]; | |
} | |
export {useFetchSerial}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment