Skip to content

Commit c0da784

Browse files
committed
some modify in useFetch.js
1 parent 44defe3 commit c0da784

File tree

1 file changed

+81
-0
lines changed

1 file changed

+81
-0
lines changed

frontend/src/hooks/useFetch.js

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
import { useState, useEffect } from "react";
2+
import axios from "axios";
3+
import { useAuth } from "../context/AuthContext"; // To potentially use the JWT token
4+
5+
/**
6+
* Custom hook for fetching data from an API endpoint.
7+
* Handles loading, data, and error states, and includes JWT authorization.
8+
* * @param {string} url - The API endpoint URL to fetch from.
9+
* @param {object} options - Optional Axios request configuration (e.g., method, data).
10+
* @returns {{data: any, loading: boolean, error: Error | null, refetch: () => void}}
11+
*/
12+
const useFetch = (url, options = {}) => {
13+
const [data, setData] = useState(null);
14+
const [loading, setLoading] = useState(true);
15+
const [error, setError] = useState(null);
16+
17+
// Get the current JWT token from context (or local storage directly)
18+
// NOTE: This assumes useAuth is working and provides the token or access to it.
19+
const { token } = useAuth();
20+
21+
const fetchApiData = async (signal) => {
22+
setLoading(true);
23+
setError(null);
24+
25+
try {
26+
const headers = {
27+
"Content-Type": "application/json",
28+
...options.headers,
29+
};
30+
31+
// If a token exists, add the Authorization header
32+
if (token) {
33+
headers["Authorization"] = `Bearer ${token}`;
34+
}
35+
36+
const response = await axios({
37+
method: "GET", // Default to GET
38+
url,
39+
signal,
40+
...options,
41+
headers: headers,
42+
});
43+
44+
setData(response.data);
45+
} catch (err) {
46+
if (axios.isCancel(err)) {
47+
// Ignore AbortController cancellation errors
48+
return;
49+
}
50+
setError(err);
51+
console.error(`Error fetching ${url}:`, err);
52+
} finally {
53+
// Ensure loading is set to false, even on error
54+
if (!signal.aborted) {
55+
setLoading(false);
56+
}
57+
}
58+
};
59+
60+
useEffect(() => {
61+
// AbortController prevents state updates on unmounted components
62+
const controller = new AbortController();
63+
const signal = controller.signal;
64+
65+
fetchApiData(signal);
66+
67+
// Cleanup function to cancel the request if the component unmounts
68+
return () => {
69+
controller.abort();
70+
};
71+
}, [url, token]); // Re-run if URL or token changes
72+
73+
// Function to manually trigger a refetch
74+
const refetch = () => {
75+
fetchApiData(new AbortController().signal);
76+
};
77+
78+
return { data, loading, error, refetch };
79+
};
80+
81+
export default useFetch;

0 commit comments

Comments
 (0)