Skip to content

Commit 7d6cd07

Browse files
committed
feat: cache in axios request
1 parent b076189 commit 7d6cd07

File tree

6 files changed

+80
-8
lines changed

6 files changed

+80
-8
lines changed

src/api/api.ts

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,32 @@
1-
import axios, { AxiosRequestHeaders } from 'axios';
1+
import axios, { AxiosRequestHeaders, InternalAxiosRequestConfig } from 'axios';
2+
import { getCacheRequestData, handleCacheResponse } from './cache';
23

34
const api = axios.create({
45
baseURL: import.meta.env.VITE_API_URL ?? 'http://localhost:4000/',
56
});
67

7-
api.interceptors.request.use((config) => {
8-
if (!config.headers) config.headers = {} as AxiosRequestHeaders;
8+
function handleRequestAuthToken(config: InternalAxiosRequestConfig<any>) {
99
const token = localStorage.getItem('token');
1010
if (token) config.headers.Authorization = `Bearer ${token}`;
11+
}
12+
13+
api.interceptors.request.use((config) => {
14+
if (!config.headers) config.headers = {} as AxiosRequestHeaders;
15+
handleRequestAuthToken(config);
16+
const response = getCacheRequestData(config);
17+
if (response) {
18+
config.adapter = () => {
19+
return new Promise((resolve) => {
20+
resolve({ ...response, config });
21+
});
22+
};
23+
}
1124
return config;
1225
});
1326

1427
api.interceptors.response.use(
1528
(config) => {
29+
handleCacheResponse(config);
1630
return config;
1731
},
1832
(error) => {

src/api/cache.ts

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import { AxiosResponse, InternalAxiosRequestConfig } from 'axios';
2+
3+
function getCacheRequestData(config: InternalAxiosRequestConfig<any>) {
4+
if (
5+
config.method === 'get' &&
6+
config.url &&
7+
config.headers['x-app-cache'] === 'true'
8+
) {
9+
const cache = localStorage.getItem(config.url);
10+
if (cache) {
11+
const { data, timestamp } = JSON.parse(cache);
12+
const ttl = 1000 * 60 * 5; // 5 minutes
13+
if (new Date().getTime() - timestamp >= ttl) {
14+
console.log(`cache - expirado - ${config.url}`);
15+
localStorage.removeItem(config.url);
16+
} else {
17+
console.log(`cache - ok - ${config.url}`);
18+
return data;
19+
}
20+
}
21+
}
22+
return null;
23+
}
24+
25+
function handleCacheResponse(resp: AxiosResponse<any, any>) {
26+
if (
27+
resp.config.method === 'get' &&
28+
resp.config.url &&
29+
resp.config.headers['x-app-cache'] === 'true' &&
30+
resp.status >= 200 &&
31+
resp.status < 300
32+
) {
33+
const { data, headers, status, statusText } = resp;
34+
localStorage.setItem(
35+
resp.config.url,
36+
JSON.stringify({
37+
data: { data, headers, status, statusText },
38+
timestamp: new Date().getTime(),
39+
})
40+
);
41+
}
42+
}
43+
44+
export { handleCacheResponse, getCacheRequestData };

src/hooks/useFetch/types.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
export interface IUseFetchOptions<T> {
2+
cache?: boolean;
3+
initialValue?: T;
4+
}

src/hooks/useFetch/useFetch.tsx

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,24 @@ import { AxiosRequestConfig } from 'axios';
33

44
import { api } from '@/api';
55
import { IServerResponse } from '@/types';
6+
import { IUseFetchOptions } from './types';
67

7-
function useFetch<T = any>(path: string, initialValue?: T) {
8+
function useFetch<T = any>(path: string, options: IUseFetchOptions<T> = {}) {
9+
const { cache, initialValue } = options;
810
const [loading, setLoading] = useState<boolean>(true);
911
const [data, setData] = useState<T>(initialValue || ({} as T));
1012

1113
const refresh = useCallback(
1214
(config?: AxiosRequestConfig<any>) => {
15+
const headers = config?.headers ?? {};
16+
if (cache) headers['x-app-cache'] = 'true';
1317
setLoading(true);
1418
api
15-
.get<IServerResponse<T>>(path, config)
19+
.get<IServerResponse<T>>(path, { ...config, headers })
1620
.then(({ data }) => setData(data.data))
1721
.finally(() => setLoading(false));
1822
},
19-
[path]
23+
[cache, path]
2024
);
2125

2226
useEffect(() => {

src/hooks/useSupplies/useSupplies.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@ import { useFetch } from '../useFetch';
33
import { PaginatedQueryPath } from '../usePaginatedQuery/paths';
44

55
const useSupplies = () => {
6-
return useFetch<ISupply[]>(PaginatedQueryPath.Supplies, []);
6+
return useFetch<ISupply[]>(PaginatedQueryPath.Supplies, {
7+
initialValue: [],
8+
cache: true,
9+
});
710
};
811

912
export { useSupplies };

src/hooks/useSupplyCategories/useSupplyCategories.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@ import { PaginatedQueryPath } from '../usePaginatedQuery/paths';
33
import { ISupplyCategory } from './types';
44

55
const useSupplyCategories = () => {
6-
return useFetch<ISupplyCategory[]>(PaginatedQueryPath.SupplyCategories, []);
6+
return useFetch<ISupplyCategory[]>(PaginatedQueryPath.SupplyCategories, {
7+
initialValue: [],
8+
cache: true,
9+
});
710
};
811

912
export { useSupplyCategories };

0 commit comments

Comments
 (0)