Skip to content

Instantly share code, notes, and snippets.

@brunopk
Last active October 28, 2020 22:28
Show Gist options
  • Save brunopk/48adec0adeb769ea5579162a8738ab3b to your computer and use it in GitHub Desktop.
Save brunopk/48adec0adeb769ea5579162a8738ab3b to your computer and use it in GitHub Desktop.
Generic custom hook for querying services and update components asynchronously
import {useReducer, useEffect} from 'react';
const A_FETCH_SET_PARAM = 'FETCH_SET_PARAM';
const A_FETCH_INIT = 'FETCH_INIT';
const A_FETCH_SUCCESS = 'FETCH_SUCCESS';
const A_FETCH_FAILURE = 'FETCH_FAILURE';
const A_FETCH_FAILURE_RESET = 'FETCH_FAILURE_RESET';
const INITIAL_STATE = {
isLoading: false,
isError: false,
param: null,
result: null,
};
/**
* Query service asynchronously
* @param {Function} service service
* @returns {Array} Returns an array with [result, isLoading, isError, fetch, reset]
* - Initial values: [null, false, false, Function, Function]
* - fetch: (params) -> {} function to trigger the hook
* - reset: () -> null function to reset the hook in case of error (isError == true)
*/
function useFetchService(service) {
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,
};
case A_FETCH_SET_PARAM:
return {
...prevState,
param: action.param,
};
default:
case A_FETCH_FAILURE_RESET:
return INITIAL_STATE;
}
}, INITIAL_STATE);
useEffect(() => {
const fetchData = async () => {
try {
dispatch({type: A_FETCH_INIT});
let res = await service(state.param);
dispatch({type: A_FETCH_SUCCESS, data: res});
} catch (error) {
console.error(error);
dispatch({type: A_FETCH_FAILURE});
}
}
if (state.param !== null) {
fetchData();
}
}, [state.param, service]);
return [
state.result,
state.isLoading,
state.isError,
(param) => dispatch({type: A_FETCH_SET_PARAM, param}),
() => dispatch({type: A_FETCH_FAILURE_RESET}),
];
}
export {useFetchService};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment