Skip to content

Commit 313d8bb

Browse files
authored
fix(performanceNews): 공연 등록 중복 route 수정 (#437)
* feat(performanceNews): 공연 소식 페이지 기본 구성 구현 * feat(performanceNews): 전체 탭 구현 * feat(performanceNews): 세부 탭 구현 * feat(performanceNews): 공연 등록 페이지 ui 구현 * feat(performanceNews): 공연 소식 전체탭 api 연동 * feat(performanceNews): 공연 소식 세부탭 api 연동 * feat(performanceNews): 공연 소식 등록 api 연동 * feat(performanceNews): 공연 소식 상세 api 연동 * feat(performanceNews): 공연 소식 수정 api 연동 * feat(performanceNews): 링크 이동 모달 구현 * fix(performanceNews): 공연 등록 중복 route 수정
1 parent 14fa860 commit 313d8bb

3 files changed

Lines changed: 45 additions & 37 deletions

File tree

src/App.jsx

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -235,14 +235,7 @@ function App() {
235235

236236
<Route path="mypage/infochange" element={<AccountInfoChange />} />
237237
<Route path="/performanceNews" element={<PerformanceNews />} />
238-
<Route
239-
path="/performanceNews/register"
240-
element={
241-
<ProtectedRoute>
242-
<AddPerformanceNews />
243-
</ProtectedRoute>
244-
}
245-
/>
238+
246239
<Route path="/performanceNews/edit/:id"
247240
element={
248241
<ProtectedRoute>

src/pages/performanceNews/addPerformanceNews.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,17 @@ const AddPerformanceNews = ({ mode }: { mode: "create" | "edit" }) => {
3535
const fileInputRef = useRef<HTMLInputElement | null>(null);
3636
const posterPreviewUrl = useMemo(() => {
3737
if (posterFile) return URL.createObjectURL(posterFile);
38+
3839
return posterPreview; // 기존 이미지
3940
}, [posterFile, posterPreview]);
4041
const { mutateAsync, isPending } = useRegisterPerformance();
42+
43+
const isEdit = mode === "edit" && Boolean(id);
4144
const {
4245
data: detailData,
4346
isLoading: isDetailLoading,
4447
isError: isDetailError,
45-
} = usePerformanceDetail(id ?? "", true);
48+
} = usePerformanceDetail(id ?? "", isEdit);
4649

4750
useEffect(() => {
4851
if (mode !== "edit" || !detailData) return;
@@ -102,6 +105,7 @@ const AddPerformanceNews = ({ mode }: { mode: "create" | "edit" }) => {
102105

103106
try {
104107
if (mode === "create") {
108+
console.log("등록");
105109
const poster = posterFile ?? (await getDefaultPosterFile());
106110
const ok = await mutateAsync({
107111
poster,
@@ -117,7 +121,7 @@ const AddPerformanceNews = ({ mode }: { mode: "create" | "edit" }) => {
117121
else setErrorMessage("등록에 실패했습니다. 잠시 후 다시 시도해주세요.");
118122
return;
119123
}
120-
124+
console.log("수정");
121125
// ---- edit ----
122126
if (!id) {
123127
setErrorMessage("공연 소식 id가 없습니다.");

src/routes/ProtectedRoute.tsx

Lines changed: 38 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import Cookies from "js-cookie";
2-
import { useContext, useEffect, useRef } from "react";
2+
import { useContext, useEffect, useState } from "react";
33
import { useLocation, useNavigate } from "react-router-dom";
4-
import { ReactNode } from "react";
4+
import type { ReactNode } from "react";
55
import AuthContext from "@/contexts/AuthContext";
66

77
interface ProtectedRouteProps {
@@ -10,35 +10,46 @@ interface ProtectedRouteProps {
1010

1111
const ProtectedRoute = ({ children }: ProtectedRouteProps) => {
1212
const { isAuthenticated, refreshAccessToken } = useContext(AuthContext);
13+
const [checked, setChecked] = useState(false);
14+
1315
const navigate = useNavigate();
1416
const location = useLocation();
1517

16-
const checkedAuthFlag = useRef<boolean>(false);
17-
1818
useEffect(() => {
19-
if (checkedAuthFlag.current) return;
20-
21-
if (!Cookies.get("accessToken")) {
22-
(async () => {
23-
const newAccessToken = await refreshAccessToken();
24-
25-
if (!newAccessToken) {
26-
alert("로그인이 필요한 서비스입니다.");
27-
navigate("/signin", {
28-
replace: true,
29-
state: { from: location },
30-
});
31-
}
32-
33-
checkedAuthFlag.current = true;
34-
})();
35-
} else {
36-
checkedAuthFlag.current = true;
37-
}
38-
}, [navigate, refreshAccessToken, location]);
39-
40-
// ✅ 인증된 경우에만 렌더
41-
return isAuthenticated ? children : null;
19+
let mounted = true;
20+
21+
const run = async () => {
22+
const hasToken = Boolean(Cookies.get("accessToken"));
23+
24+
// 이미 인증 상태면 통과
25+
if (isAuthenticated || hasToken) {
26+
if (mounted) setChecked(true);
27+
return;
28+
}
29+
30+
// 토큰 없으면 refresh 시도
31+
const newToken = await refreshAccessToken();
32+
33+
if (!newToken) {
34+
alert("로그인이 필요한 서비스입니다.");
35+
navigate("/signin", { replace: true, state: { from: location } });
36+
return;
37+
}
38+
39+
// refresh 성공이면 통과(컨텍스트 갱신 타이밍과 무관하게)
40+
if (mounted) setChecked(true);
41+
};
42+
43+
run();
44+
45+
return () => {
46+
mounted = false;
47+
};
48+
}, [isAuthenticated, refreshAccessToken, navigate, location]);
49+
50+
if (!checked) return null; // 또는 로딩 컴포넌트
51+
52+
return <>{children}</>;
4253
};
4354

4455
export default ProtectedRoute;

0 commit comments

Comments
 (0)