82 lines
2.3 KiB
JavaScript
82 lines
2.3 KiB
JavaScript
import { useState, useRef, useCallback, useEffect } from 'react';
|
|
|
|
import api from 'shared/utils/api';
|
|
import useDeepCompareMemoize from './deepCompareMemoize';
|
|
|
|
const useApi = (method, url, variables = {}, { lazy = false } = {}) => {
|
|
const isCalledAutomatically = method === 'get' && !lazy;
|
|
|
|
const [state, setState] = useState({
|
|
data: null,
|
|
error: null,
|
|
isLoading: isCalledAutomatically,
|
|
additionalVariables: {},
|
|
});
|
|
|
|
const setStateMerge = newState => setState(currentState => ({ ...currentState, ...newState }));
|
|
|
|
const wasCalledRef = useRef(false);
|
|
const variablesMemoized = useDeepCompareMemoize(variables);
|
|
|
|
const stateRef = useRef();
|
|
stateRef.current = state;
|
|
|
|
const makeRequest = useCallback(
|
|
(newVariables = {}) =>
|
|
new Promise((resolve, reject) => {
|
|
const additionalVariables = { ...stateRef.current.additionalVariables, ...newVariables };
|
|
|
|
if (!isCalledAutomatically || wasCalledRef.current) {
|
|
setStateMerge({ additionalVariables, isLoading: true });
|
|
}
|
|
|
|
api[method](url, { ...variablesMemoized, ...additionalVariables }).then(
|
|
data => {
|
|
resolve(data);
|
|
setStateMerge({ data, error: null, isLoading: false });
|
|
},
|
|
error => {
|
|
reject(error);
|
|
setStateMerge({ error, data: null, isLoading: false });
|
|
},
|
|
);
|
|
|
|
wasCalledRef.current = true;
|
|
}),
|
|
[method, variablesMemoized, isCalledAutomatically, url],
|
|
);
|
|
|
|
useEffect(() => {
|
|
if (isCalledAutomatically) {
|
|
makeRequest();
|
|
}
|
|
}, [makeRequest, isCalledAutomatically]);
|
|
|
|
const setLocalData = useCallback(
|
|
getUpdatedData =>
|
|
setState(currentState => ({ ...currentState, data: getUpdatedData(currentState.data) })),
|
|
[],
|
|
);
|
|
|
|
const result = [
|
|
{
|
|
...state,
|
|
wasCalled: wasCalledRef.current,
|
|
variables: { ...variablesMemoized, ...state.additionalVariables },
|
|
setLocalData,
|
|
},
|
|
makeRequest,
|
|
];
|
|
|
|
return result;
|
|
};
|
|
|
|
/* eslint-disable react-hooks/rules-of-hooks */
|
|
export default {
|
|
get: (...args) => useApi('get', ...args),
|
|
post: (...args) => useApi('post', ...args),
|
|
put: (...args) => useApi('put', ...args),
|
|
patch: (...args) => useApi('patch', ...args),
|
|
delete: (...args) => useApi('delete', ...args),
|
|
};
|