ahooks
Version:
react hooks library
119 lines (118 loc) • 4.58 kB
JavaScript
import { useRef } from 'react';
import useCreation from '../../../useCreation';
import useUnmount from '../../../useUnmount';
import { setCache, getCache } from '../utils/cache';
import { setCachePromise, getCachePromise } from '../utils/cachePromise';
import { trigger, subscribe } from '../utils/cacheSubscribe';
const useCachePlugin = (fetchInstance, { cacheKey, cacheTime = 5 * 60 * 1000, staleTime = 0, setCache: customSetCache, getCache: customGetCache, }) => {
const unSubscribeRef = useRef(undefined);
const currentPromiseRef = useRef(undefined);
const _setCache = (key, cachedData) => {
if (customSetCache) {
customSetCache(cachedData);
}
else {
setCache(key, cacheTime, cachedData);
}
trigger(key, cachedData.data);
};
const _getCache = (key, params = []) => {
if (customGetCache) {
return customGetCache(params);
}
return getCache(key);
};
useCreation(() => {
if (!cacheKey) {
return;
}
// get data from cache when init
const cacheData = _getCache(cacheKey);
if (cacheData && Object.hasOwnProperty.call(cacheData, 'data')) {
fetchInstance.state.data = cacheData.data;
fetchInstance.state.params = cacheData.params;
if (staleTime === -1 || Date.now() - cacheData.time <= staleTime) {
fetchInstance.state.loading = false;
}
}
// subscribe same cachekey update, trigger update
unSubscribeRef.current = subscribe(cacheKey, (data) => {
fetchInstance.setState({ data });
});
}, []);
useUnmount(() => {
var _a;
(_a = unSubscribeRef.current) === null || _a === void 0 ? void 0 : _a.call(unSubscribeRef);
});
if (!cacheKey) {
return {};
}
return {
onBefore: (params) => {
const cacheData = _getCache(cacheKey, params);
if (!cacheData || !Object.hasOwnProperty.call(cacheData, 'data')) {
return {};
}
// If the data is fresh, stop request
if (staleTime === -1 || Date.now() - cacheData.time <= staleTime) {
return {
loading: false,
data: cacheData === null || cacheData === void 0 ? void 0 : cacheData.data,
error: undefined,
returnNow: true,
};
}
else {
// If the data is stale, return data, and request continue
return {
data: cacheData === null || cacheData === void 0 ? void 0 : cacheData.data,
error: undefined,
};
}
},
onRequest: (service, args) => {
let servicePromise = getCachePromise(cacheKey);
// If has servicePromise, and is not trigger by self, then use it
if (servicePromise && servicePromise !== currentPromiseRef.current) {
return { servicePromise };
}
servicePromise = service(...args);
currentPromiseRef.current = servicePromise;
setCachePromise(cacheKey, servicePromise);
return { servicePromise };
},
onSuccess: (data, params) => {
var _a;
if (cacheKey) {
// cancel subscribe, avoid trgger self
(_a = unSubscribeRef.current) === null || _a === void 0 ? void 0 : _a.call(unSubscribeRef);
_setCache(cacheKey, {
data,
params,
time: Date.now(),
});
// resubscribe
unSubscribeRef.current = subscribe(cacheKey, (d) => {
fetchInstance.setState({ data: d });
});
}
},
onMutate: (data) => {
var _a;
if (cacheKey) {
// cancel subscribe, avoid trigger self
(_a = unSubscribeRef.current) === null || _a === void 0 ? void 0 : _a.call(unSubscribeRef);
_setCache(cacheKey, {
data,
params: fetchInstance.state.params,
time: Date.now(),
});
// resubscribe
unSubscribeRef.current = subscribe(cacheKey, (d) => {
fetchInstance.setState({ data: d });
});
}
},
};
};
export default useCachePlugin;