Skip to content

Commit ae50f87

Browse files
committed
Merge branch 'develop'
2 parents ea162a2 + ac3dec6 commit ae50f87

File tree

3 files changed

+92
-40
lines changed

3 files changed

+92
-40
lines changed

src/apis/axios.ts

Lines changed: 70 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,31 @@
1-
import axios, { AxiosError } from 'axios';
2-
import { getCookie } from '../utils/cookies';
3-
import { setCookie } from '../utils/cookies';
1+
import axios, {
2+
AxiosError,
3+
AxiosHeaders,
4+
InternalAxiosRequestConfig,
5+
} from 'axios';
6+
import { getCookie, setCookie } from '../utils/cookies';
47
import { reIssueToken } from './auth';
58

69
export const instance = axios.create({
710
baseURL: process.env.REACT_APP_BASE_URL,
811
timeout: 10000,
912
});
13+
let isRefreshing = false;
14+
let refreshSubscribers: ((token: string) => void)[] = [];
15+
16+
const onRefreshed = (token: string) => {
17+
refreshSubscribers.forEach((callback) => callback(token));
18+
refreshSubscribers = [];
19+
};
1020

1121
instance.interceptors.request.use(
1222
(config) => {
1323
const accessToken = getCookie('access_token');
1424
if (accessToken) {
15-
config.headers = config.headers ?? {};
16-
config.headers.Authorization = `Bearer ${accessToken}`;
25+
config.headers = new AxiosHeaders({
26+
...config.headers,
27+
Authorization: `Bearer ${accessToken}`,
28+
});
1729
}
1830
return config;
1931
},
@@ -22,39 +34,65 @@ instance.interceptors.request.use(
2234

2335
instance.interceptors.response.use(
2436
(response) => response,
25-
async (error: AxiosError<AxiosError>) => {
26-
if (axios.isAxiosError(error) && error.response) {
27-
const { config } = error;
37+
async (error: AxiosError) => {
38+
const originalRequest = error.config as InternalAxiosRequestConfig & {
39+
_retry?: boolean;
40+
};
41+
42+
if (error.response?.status === 401 || error.response?.status === 403) {
2843
const refreshToken = getCookie('refresh_token');
29-
if (error.response.data.message === 'Expired Token') {
30-
if (refreshToken) {
31-
try {
32-
const res = await reIssueToken(refreshToken);
33-
const accessExpired = new Date(res.access_token_expired_at);
34-
const refreshExpired = new Date(res.refresh_token_expired_at);
35-
36-
setCookie('access_token', res.access_token, {
37-
expires: accessExpired,
38-
});
3944

40-
setCookie('refresh_token', res.refresh_token, {
41-
expires: refreshExpired,
42-
});
45+
if (!refreshToken) {
46+
window.location.href = '/login';
47+
return Promise.reject(error);
48+
}
4349

44-
if (config?.headers)
45-
config.headers['Authorization'] = `Bearer ${res.access_token}`;
46-
47-
return axios(config!);
48-
} catch (error) {
49-
return Promise.reject(error);
50-
}
51-
} else {
52-
window.location.href = '/login';
53-
}
54-
} else {
50+
if (originalRequest._retry) {
5551
return Promise.reject(error);
5652
}
53+
originalRequest._retry = true;
54+
55+
if (isRefreshing) {
56+
return new Promise((resolve) => {
57+
refreshSubscribers.push((token: string) => {
58+
originalRequest.headers = new AxiosHeaders({
59+
...originalRequest.headers,
60+
Authorization: `Bearer ${token}`,
61+
});
62+
resolve(instance(originalRequest));
63+
});
64+
});
65+
}
66+
67+
isRefreshing = true;
68+
69+
try {
70+
const res = await reIssueToken(refreshToken);
71+
const newAccessToken = res.access_token;
72+
73+
setCookie('access_token', newAccessToken, {
74+
expires: new Date(res.access_token_expired_at),
75+
});
76+
77+
setCookie('refresh_token', res.refresh_token, {
78+
expires: new Date(res.refresh_token_expired_at),
79+
});
80+
81+
isRefreshing = false;
82+
onRefreshed(newAccessToken);
83+
84+
originalRequest.headers = new AxiosHeaders({
85+
...originalRequest.headers,
86+
Authorization: `Bearer ${newAccessToken}`,
87+
});
88+
return instance(originalRequest);
89+
} catch (err) {
90+
isRefreshing = false;
91+
window.location.href = '/login';
92+
return Promise.reject(err);
93+
}
5794
}
95+
5896
return Promise.reject(error);
5997
},
6098
);

src/pages/Volunteer/Application.tsx

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,21 @@ export const VolunteerApplication = () => {
1717
initTheme.get('theme') === 'dark' ? THEME.DARK : THEME.LIGHT,
1818
);
1919

20-
const { data } = useGetVolunteer();
20+
const { data, isLoading, isError } = useGetVolunteer();
2121

2222
const [applications, setApplications] = useState<any[]>([]);
2323

2424
useEffect(() => {
25-
console.log('연동 성공! 데이터:', data);
26-
setApplications(data?.volunteers || []);
27-
}, [data]);
25+
if (isLoading) return;
26+
if (isError) {
27+
console.error('봉사 데이터 불러오기 실패함');
28+
return;
29+
}
30+
if (data) {
31+
console.log('연동 성공! 데이터:', data);
32+
setApplications(data.volunteers || []);
33+
}
34+
}, [data, isLoading, isError]);
2835

2936
const removeApplication = (volunteerId: string) => {
3037
setApplications((prevApplications) =>

src/pages/Volunteer/History.tsx

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,19 @@ export const VolunteerHistory = () => {
1919
initTheme.get('theme') === 'dark' ? THEME.DARK : THEME.LIGHT,
2020
);
2121

22-
const { data } = useGetMyVolunteers();
22+
const { data, isLoading, isError } = useGetMyVolunteers();
2323

2424
useEffect(() => {
25-
console.log('연동 성공! 데이터:', data);
26-
setHistories(data?.volunteer_applications || []);
27-
}, [data]);
25+
if (isLoading) return;
26+
if (isError) {
27+
console.error('봉사 데이터 불러오기 실패함');
28+
return;
29+
}
30+
if (data) {
31+
console.log('연동 성공! 데이터:', data);
32+
setHistories(data.volunteer_applications || []);
33+
}
34+
}, [data, isLoading, isError]);
2835

2936
return (
3037
<Wrapper>

0 commit comments

Comments
 (0)