@nutgaard/use-fetch
Version:
A useFetch hook to be used with react@^16.8.0
144 lines (136 loc) • 5.51 kB
JavaScript
import useAsync__default, { Status } from '@nutgaard/use-async';
export * from '@nutgaard/use-async';
import { useCallback, useMemo, useState } from 'react';
/*! *****************************************************************************
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
this file except in compliance with the License. You may obtain a copy of the
License at http://www.apache.org/licenses/LICENSE-2.0
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
MERCHANTABLITY OR NON-INFRINGEMENT.
See the Apache Version 2.0 License for specific language governing permissions
and limitations under the License.
***************************************************************************** */
var __assign = function() {
__assign = Object.assign || function __assign(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
var FetchCache = /** @class */ (function () {
function FetchCache() {
this.cache = {};
this.resolvedCache = {};
}
FetchCache.prototype.fetch = function (key, url, init) {
var _this = this;
if (this.hasKey(key)) {
return this.get(key);
}
var result = fetch(url, init);
this.put(key, result);
result.then(function (resp) {
if (!resp.ok) {
_this.remove(key);
}
}, function () {
_this.remove(key);
});
return result.then(function (resp) { return resp.clone(); });
};
FetchCache.prototype.get = function (key) {
return this.cache[key].then(function (resp) { return resp.clone(); });
};
FetchCache.prototype.getResolved = function (key) {
return this.resolvedCache[key];
};
FetchCache.prototype.putResolved = function (key, value) {
this.resolvedCache[key] = value;
};
FetchCache.prototype.put = function (key, value) {
this.cache[key] = value.then(function (resp) { return resp.clone(); });
};
FetchCache.prototype.remove = function (key) {
delete this.cache[key];
delete this.resolvedCache[key];
};
FetchCache.prototype.clear = function () {
this.cache = {};
this.resolvedCache = {};
};
FetchCache.prototype.hasKey = function (key) {
// tslint:disable-next-line:strict-type-predicates
return this.cache[key] !== undefined;
};
FetchCache.prototype.keys = function () {
return Object.keys(this.cache);
};
FetchCache.prototype.hasKeyResolved = function (key) {
// tslint:disable-next-line:strict-type-predicates
return this.resolvedCache[key] !== undefined;
};
FetchCache.prototype.size = function () {
return Object.keys(this.cache).length;
};
return FetchCache;
}());
var globaleFetchCache = new FetchCache();
function createCacheKey(url, option) {
var method = (option && option.method) || 'GET';
var body = (option && option.body && option.body.toString()) || '';
var headers = (option && option.headers && JSON.stringify(option.headers)) || '';
return [url, method.toUpperCase(), body, headers].join('||');
}
function setCacheKeyGenerator(keygenerator) {
cacheKeyCreator = keygenerator;
}
var cacheKeyCreator = createCacheKey;
function handleResponse(response, setStatusCode, cacheKey) {
return response
.then(function (resp) {
setStatusCode(resp.status);
if (!resp.ok) {
throw new Error(resp.statusText);
}
if ([200, 201, 203, 206].includes(resp.status)) {
return resp.json();
}
return;
})
.then(function (json) {
globaleFetchCache.putResolved(cacheKey, json);
return json;
});
}
function useFetch(url, option, config) {
if (config === void 0) { config = {
lazy: false,
cacheKey: undefined
}; }
var _a = useState(-1), statusCode = _a[0], setStatusCode = _a[1];
var cacheKey = config.cacheKey || cacheKeyCreator(url, option);
var source = useCallback(function (isRerun) {
setStatusCode(-1);
var response = isRerun ? fetch(url, option) : globaleFetchCache.fetch(cacheKey, url, option);
if (isRerun) {
globaleFetchCache.put(cacheKey, response);
}
return handleResponse(response, setStatusCode, cacheKey);
}, [url, option, cacheKey]);
var initialConfig = globaleFetchCache.hasKeyResolved(cacheKey)
? { status: Status.OK, data: globaleFetchCache.getResolved(cacheKey) }
: undefined;
var asyncResult = useAsync__default(source, config.lazy, [source], initialConfig);
return useMemo(function () {
return __assign({}, asyncResult, { statusCode: statusCode });
}, [asyncResult, statusCode]);
}
export default useFetch;
export { createCacheKey, setCacheKeyGenerator, globaleFetchCache as cache };
//# sourceMappingURL=use-fetch.es5.js.map