Files
Tom Moor 084490ba6b chore: Remove React in scope requirement (#9261)
* Add rules

* codemod: update-react-imports

* Update babelrc
2025-05-20 19:26:11 -04:00

66 lines
1.8 KiB
TypeScript

import { useState, useCallback, useEffect } from "react";
import useIsMounted from "./useIsMounted";
type RequestResponse<T> = {
/** The return value of the request function. */
data: T | undefined;
/** The request error, if any. */
error: unknown;
/** Whether the request is currently in progress. */
loading: boolean;
/** Whether the request has completed - useful to check if the request has completed at least once. */
loaded: boolean;
/** Function to start the request. */
request: () => Promise<T | undefined>;
};
/**
* A hook to make an API request and track its state within a component.
*
* @param requestFn The function to call to make the request, it should return a promise.
* @param makeRequestOnMount Whether to make the request when the component mounts.
* @returns An object containing the request state and a function to start the request.
*/
export default function useRequest<T = unknown>(
requestFn: () => Promise<T>,
makeRequestOnMount = false
): RequestResponse<T> {
const isMounted = useIsMounted();
const [data, setData] = useState<T>();
const [loading, setLoading] = useState<boolean>(false);
const [loaded, setLoaded] = useState<boolean>(false);
const [error, setError] = useState();
const request = useCallback(async () => {
setLoading(true);
try {
const response = await requestFn();
if (isMounted()) {
setData(response);
setError(undefined);
setLoaded(true);
}
return response;
} catch (err) {
if (isMounted()) {
setError(err);
}
} finally {
if (isMounted()) {
setLoading(false);
}
}
return undefined;
}, [requestFn, isMounted]);
useEffect(() => {
if (makeRequestOnMount) {
void request();
}
}, []);
return { data, loading, loaded, error, request };
}