@simonkov/use-axios
Version:
A custom React hook that provides a state-driven interface for Axios requests.
83 lines • 2.81 kB
JavaScript
import axios, { AxiosError } from "axios";
import React, { useEffect } from "react";
import { flushSync } from "react-dom";
const RESET_STATE_FLAGS = {
isFinished: false,
isAborted: false,
isLoading: false,
isPending: false,
isSuccess: false,
isError: false,
isConcurrencyFailure: false
};
export function useAxios(requestConfig, options) {
const invocationCount = React.useRef(0);
const [state, setState] = React.useState({
...RESET_STATE_FLAGS,
response: null,
error: null,
isPending: true
});
function request(config) {
const mergedConfig = { ...requestConfig, ...config };
const request = (options?.instance || axios).request(mergedConfig);
const maybeIntercepted = options?.intercept === undefined ? request : options.intercept(request);
setState((curr) => ({
...curr,
...RESET_STATE_FLAGS,
isLoading: true
}));
return new Promise((resolve, reject) => {
if (options?.preventConcurrent && invocationCount.current !== 0) {
setState((curr) => ({
...curr,
...RESET_STATE_FLAGS,
isConcurrencyFailure: true
}));
const error = new AxiosError("Concurrency failure", "ERROR_CONCURRENCY_FAILURE", config);
reject(error);
return;
}
++invocationCount.current;
maybeIntercepted.then((response) => {
queueMicrotask(() => {
flushSync(() => {
setState((curr) => ({
...curr,
...RESET_STATE_FLAGS,
isFinished: true,
isSuccess: true,
response
}));
resolve(response);
});
});
})
.catch((error) => {
queueMicrotask(() => {
flushSync(() => {
setState((curr) => ({
...curr,
...RESET_STATE_FLAGS,
isFinished: true,
isError: true,
error
}));
reject(error);
});
});
})
.finally(() => {
--invocationCount.current;
});
});
}
if (options?.immediate) {
useEffect(() => {
request(requestConfig);
}, []);
return state;
}
return [request, state];
}
//# sourceMappingURL=main.js.map