use-invariant
Version:
- <a target="_blank" rel="noopener noreferrer" href='https://codesandbox.io/s/usefetch-in-nextjs-nn9fm'>Example - Next.js</a> - <a target="_blank" rel="noopener noreferrer" href='https://codesandbox.io/embed/km04k9k9x5'>Examples - create-react-app</a>
131 lines • 6.15 kB
JavaScript
;
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const react_1 = require("react");
const FetchContext_1 = __importDefault(require("./FetchContext"));
const types_1 = require("./types");
const utils_1 = require("./utils");
function useFetch(arg1, arg2) {
const context = react_1.useContext(FetchContext_1.default);
utils_1.invariant(!!arg1 && !!context.url, 'The first argument of useFetch is required unless you have a global url setup like: <Provider url="https://example.com"></Provider>');
let url = context.url || null;
let options = {};
let onMount = false;
let baseUrl = '';
let method = types_1.HTTPMethod.GET;
const handleOptions = react_1.useCallback((opts) => {
if (true) {
// take out all the things that are not normal `fetch` options
// need to take this out of scope so can set the variables below correctly
let { url, onMount, timeout, baseUrl } = opts, rest = __rest(opts, ["url", "onMount", "timeout", "baseUrl"]);
options = Object.assign({ signal: undefined }, rest);
}
if (context.url)
url = context.url;
if (opts.url)
url = opts.url || context.url || '';
if (opts.onMount)
onMount = opts.onMount;
if (opts.method)
method = opts.method;
if (opts.baseUrl)
baseUrl = opts.baseUrl;
}, []);
if (typeof arg1 === 'string') {
// if we have a default url from context, and
// arg1 is a string, and we're not using graphql
// we treat arg1 as a relative route
url = context.url && !context.graphql ? context.url + arg1 : arg1;
if (arg2 && utils_1.isObject(arg2))
handleOptions(arg2);
}
else if (utils_1.isObject(arg1)) {
handleOptions(arg1 || {});
}
const [data, setData] = react_1.useState();
const [loading, setLoading] = react_1.useState(onMount);
const [error, setError] = react_1.useState();
const controller = react_1.useRef();
const fetchData = react_1.useCallback((method) => (fetchArg1, fetchArg2) => __awaiter(this, void 0, void 0, function* () {
if ('AbortController' in window) {
controller.current = new AbortController();
options.signal = controller.current.signal;
}
let query = '';
// post | patch | put | etc.
if (utils_1.isObject(fetchArg1) && method.toLowerCase() !== 'get') {
options.body = JSON.stringify(fetchArg1);
// relative routes
}
else if (baseUrl && typeof fetchArg1 === 'string') {
url = baseUrl + fetchArg1;
if (utils_1.isObject(fetchArg2))
options.body = JSON.stringify(fetchArg2);
}
if (typeof fetchArg1 === 'string' && typeof fetchArg2 === 'string')
query = fetchArg2;
try {
setLoading(true);
const response = yield fetch(url + query, Object.assign({ method }, context.options, options, { headers: Object.assign({
// default content types http://bit.ly/2N2ovOZ
Accept: 'application/json', 'Content-Type': 'application/json' }, (context.options || {}).headers, options.headers) }));
let data = null;
try {
data = yield response.json();
}
catch (err) {
data = yield response.text();
}
setData(data);
}
catch (err) {
if (err.name !== 'AbortError')
setError(err);
}
finally {
controller.current = null;
setLoading(false);
}
}), [url]);
const get = react_1.useCallback(fetchData(types_1.HTTPMethod.GET), []);
const post = react_1.useCallback(fetchData(types_1.HTTPMethod.POST), []);
const patch = react_1.useCallback(fetchData(types_1.HTTPMethod.PATCH), []);
const put = react_1.useCallback(fetchData(types_1.HTTPMethod.PUT), []);
const del = react_1.useCallback(fetchData(types_1.HTTPMethod.DELETE), []);
const query = react_1.useCallback((query, variables) => post({ query, variables }), []);
const mutate = react_1.useCallback((mutation, variables) => post({ mutation, variables }), []);
const abort = react_1.useCallback(() => {
controller.current && controller.current.abort();
}, []);
const request = react_1.useMemo(() => ({ get, post, patch, put, del, delete: del, abort, query, mutate }), []);
react_1.useEffect(() => {
const methodName = method.toLowerCase();
if (onMount)
request[methodName]();
}, []);
return Object.assign([data, loading, error, request], Object.assign({ data, loading, error, request }, request));
}
exports.useFetch = useFetch;
exports.default = useFetch;
//# sourceMappingURL=useFetch.js.map