-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathuseFetch.tsx
60 lines (51 loc) · 1.57 KB
/
useFetch.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
import { useState, useEffect, useRef } from "react";
import axios, { AxiosRequestConfig, AxiosResponse } from "axios";
import axiosInstance from "../api/axiosInstance";
type HttpMethod = "GET" | "POST" | "PATCH" | "PUT" | "DELETE";
const useFetch = <T,>(
url: string,
method: HttpMethod = "GET",
options?: AxiosRequestConfig
) => {
const [data, setData] = useState<T | null>(null);
const [loading, setLoading] = useState<boolean>(true);
const [error, setError] = useState<string | null>(null);
const abortControllerRef = useRef<AbortController | null>(null);
useEffect(() => {
abortControllerRef.current = new AbortController();
const signal = abortControllerRef.current.signal;
const fetchData = async () => {
setLoading(true);
setError(null);
try {
const response: AxiosResponse<T> = await axiosInstance({
url,
method,
...options,
signal,
});
if (!response.data) {
throw new Error("Empty data");
}
setData(response.data);
} catch (err) {
if (axios.isCancel(err)) {
console.log("Request canceled: ", err.message);
} else {
setError("Failed to fetch data. Please try again.");
console.error("Request error: ", err);
}
} finally {
setLoading(false);
}
};
fetchData();
return () => {
if (abortControllerRef.current) {
abortControllerRef.current.abort();
}
};
}, [url, method, options]);
return { data, loading, error };
};
export default useFetch;