axios-hooks
Version:
279 lines • 9.02 kB
JavaScript
import _asyncToGenerator from "@babel/runtime/helpers/esm/asyncToGenerator";
import _extends from "@babel/runtime/helpers/esm/extends";
import _regeneratorRuntime from "@babel/runtime/regenerator";
import React from 'react';
import StaticAxios, { isCancel } from 'axios';
import { LRUCache } from 'lru-cache';
import { dequal as deepEqual } from 'dequal/lite';
var actions = {
REQUEST_START: 'REQUEST_START',
REQUEST_END: 'REQUEST_END'
};
var DEFAULT_OPTIONS = {
manual: false,
useCache: true,
ssr: true,
autoCancel: true
};
var useAxios = makeUseAxios();
var __ssrPromises = useAxios.__ssrPromises,
resetConfigure = useAxios.resetConfigure,
configure = useAxios.configure,
loadCache = useAxios.loadCache,
serializeCache = useAxios.serializeCache,
clearCache = useAxios.clearCache;
export default useAxios;
export { __ssrPromises, resetConfigure, configure, loadCache, serializeCache, clearCache };
function isReactEvent(obj) {
return obj && obj.nativeEvent && obj.nativeEvent instanceof Event;
}
function createCacheKey(config) {
var cleanedConfig = _extends({}, config);
delete cleanedConfig.cancelToken;
return JSON.stringify(cleanedConfig);
}
function configToObject(config) {
if (typeof config === 'string') {
return {
url: config
};
}
return Object.assign({}, config);
}
export function makeUseAxios(configureOptions) {
/**
* @type {import('lru-cache')}
*/
var cache;
var axiosInstance;
var defaultOptions;
var __ssrPromises = [];
function resetConfigure() {
cache = new LRUCache({
max: 500
});
axiosInstance = StaticAxios;
defaultOptions = DEFAULT_OPTIONS;
}
function configure(options) {
if (options === void 0) {
options = {};
}
if (options.axios !== undefined) {
axiosInstance = options.axios;
}
if (options.cache !== undefined) {
cache = options.cache;
}
if (options.defaultOptions !== undefined) {
defaultOptions = _extends({}, DEFAULT_OPTIONS, options.defaultOptions);
}
}
resetConfigure();
configure(configureOptions);
function loadCache(data) {
cache.load(data);
}
function serializeCache() {
return _serializeCache.apply(this, arguments);
}
function _serializeCache() {
_serializeCache = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee() {
var ssrPromisesCopy;
return _regeneratorRuntime.wrap(function _callee$(_context) {
while (1) switch (_context.prev = _context.next) {
case 0:
ssrPromisesCopy = [].concat(__ssrPromises);
__ssrPromises.length = 0;
_context.next = 4;
return Promise.all(ssrPromisesCopy);
case 4:
return _context.abrupt("return", cache.dump());
case 5:
case "end":
return _context.stop();
}
}, _callee);
}));
return _serializeCache.apply(this, arguments);
}
function clearCache() {
cache.clear();
}
return Object.assign(useAxios, {
__ssrPromises: __ssrPromises,
resetConfigure: resetConfigure,
configure: configure,
loadCache: loadCache,
serializeCache: serializeCache,
clearCache: clearCache
});
function tryStoreInCache(config, response) {
if (!cache) {
return;
}
var cacheKey = createCacheKey(config);
var responseForCache = _extends({}, response);
delete responseForCache.config;
delete responseForCache.request;
cache.set(cacheKey, responseForCache);
}
function createInitialState(config, options) {
var response = !options.manual && tryGetFromCache(config, options);
return _extends({
loading: !options.manual && !response,
error: null
}, response ? {
data: response.data,
response: response
} : null);
}
function reducer(state, action) {
var _extends2;
switch (action.type) {
case actions.REQUEST_START:
return _extends({}, state, {
loading: true,
error: null
});
case actions.REQUEST_END:
return _extends({}, state, {
loading: false
}, action.error ? {} : {
data: action.payload.data,
error: null
}, (_extends2 = {}, _extends2[action.error ? 'error' : 'response'] = action.payload, _extends2));
}
}
function tryGetFromCache(config, options, dispatch) {
if (!cache || !options.useCache) {
return;
}
var cacheKey = createCacheKey(config);
var response = cache.get(cacheKey);
if (response && dispatch) {
dispatch({
type: actions.REQUEST_END,
payload: response
});
}
return response;
}
function executeRequest(_x, _x2) {
return _executeRequest.apply(this, arguments);
}
function _executeRequest() {
_executeRequest = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee2(config, dispatch) {
var response;
return _regeneratorRuntime.wrap(function _callee2$(_context2) {
while (1) switch (_context2.prev = _context2.next) {
case 0:
_context2.prev = 0;
dispatch({
type: actions.REQUEST_START
});
_context2.next = 4;
return axiosInstance(config);
case 4:
response = _context2.sent;
tryStoreInCache(config, response);
dispatch({
type: actions.REQUEST_END,
payload: response
});
return _context2.abrupt("return", response);
case 10:
_context2.prev = 10;
_context2.t0 = _context2["catch"](0);
if (!isCancel(_context2.t0)) {
dispatch({
type: actions.REQUEST_END,
payload: _context2.t0,
error: true
});
}
throw _context2.t0;
case 14:
case "end":
return _context2.stop();
}
}, _callee2, null, [[0, 10]]);
}));
return _executeRequest.apply(this, arguments);
}
function request(_x3, _x4, _x5) {
return _request.apply(this, arguments);
}
function _request() {
_request = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee3(config, options, dispatch) {
return _regeneratorRuntime.wrap(function _callee3$(_context3) {
while (1) switch (_context3.prev = _context3.next) {
case 0:
return _context3.abrupt("return", tryGetFromCache(config, options, dispatch) || executeRequest(config, dispatch));
case 1:
case "end":
return _context3.stop();
}
}, _callee3);
}));
return _request.apply(this, arguments);
}
function useAxios(_config, _options) {
var config = React.useMemo(function () {
return configToObject(_config);
},
// eslint-disable-next-line react-hooks/exhaustive-deps
useDeepCompareMemoize(_config));
var options = React.useMemo(function () {
return _extends({}, defaultOptions, _options);
},
// eslint-disable-next-line react-hooks/exhaustive-deps
useDeepCompareMemoize(_options));
var abortControllerRef = React.useRef();
var _React$useReducer = React.useReducer(reducer, createInitialState(config, options)),
state = _React$useReducer[0],
dispatch = _React$useReducer[1];
if (typeof window === 'undefined' && options.ssr && !options.manual) {
useAxios.__ssrPromises.push(axiosInstance(config));
}
var cancelOutstandingRequest = React.useCallback(function () {
if (abortControllerRef.current) {
abortControllerRef.current.abort();
}
}, []);
var withAbortSignal = React.useCallback(function (config) {
if (options.autoCancel) {
cancelOutstandingRequest();
}
abortControllerRef.current = new AbortController();
config.signal = abortControllerRef.current.signal;
return config;
}, [cancelOutstandingRequest, options.autoCancel]);
React.useEffect(function () {
if (!options.manual) {
request(withAbortSignal(config), options, dispatch)["catch"](function () {});
}
return function () {
if (options.autoCancel) {
cancelOutstandingRequest();
}
};
}, [config, options, withAbortSignal, cancelOutstandingRequest]);
var refetch = React.useCallback(function (configOverride, options) {
configOverride = configToObject(configOverride);
return request(withAbortSignal(_extends({}, config, isReactEvent(configOverride) ? null : configOverride)), _extends({
useCache: false
}, options), dispatch);
}, [config, withAbortSignal]);
return [state, refetch, cancelOutstandingRequest];
}
}
function useDeepCompareMemoize(value) {
var ref = React.useRef();
var signalRef = React.useRef(0);
if (!deepEqual(value, ref.current)) {
ref.current = value;
signalRef.current += 1;
}
return [signalRef.current];
}