From 65d3e68452c91c0a8266c3a652b8b156446b41ee Mon Sep 17 00:00:00 2001
From: Jungu Lee <100949102+jobkaeHenry@users.noreply.github.com>
Date: Tue, 28 Nov 2023 03:03:54 +0900
Subject: [PATCH] =?UTF-8?q?=ED=86=A0=EC=8A=A4=ED=8A=B8=ED=8C=9D=EC=97=85-?=
=?UTF-8?q?=EA=B5=AC=ED=98=84=20(#56)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* Refactor : 리렌더 방지
* New : 글로벌팝업 에러핸들링 적용
* Minor : tsx -> ts 확장자 변경
* New : 글로벌팝업 적용
* New : 토큰제거로직 추가
---
client/src/components/ErrorPage.tsx | 6 ++--
client/src/components/GlobalToast.tsx | 12 +++++---
client/src/queries/auth/useLoginMutation.tsx | 10 +++----
client/src/queries/auth/useSignupMutation.tsx | 4 ++-
.../queries/newPost/useNewPostMutation.tsx | 3 +-
.../src/queries/post/useDeletePostMutation.ts | 9 +++---
.../src/queries/post/useLikePostMutation.tsx | 7 +++--
.../queries/post/useUnLikePostMutation.tsx | 5 ++--
client/src/queries/user/useFollowMutation.ts | 3 +-
.../src/queries/user/useUnFollowMutation.ts | 4 ++-
...dingStore.tsx => useGlobalLoadingStore.ts} | 0
client/src/store/useGlobalSnackbarStore.ts | 4 +--
client/src/utils/errorHandler.ts | 30 +++++++++++++------
13 files changed, 61 insertions(+), 36 deletions(-)
rename client/src/store/{useGlobalLoadingStore.tsx => useGlobalLoadingStore.ts} (100%)
diff --git a/client/src/components/ErrorPage.tsx b/client/src/components/ErrorPage.tsx
index 4eb7e3f..10df301 100644
--- a/client/src/components/ErrorPage.tsx
+++ b/client/src/components/ErrorPage.tsx
@@ -3,7 +3,7 @@ import { Button, Paper } from "@mui/material";
import hasErrorPage from "@/assets/images/hasError.png";
import Image from "next/image";
import { useEffect } from "react";
-import errorHandler from "@/utils/errorHandler";
+import { useErrorHandler } from "@/utils/errorHandler";
const ErrorPage = ({
error,
@@ -12,6 +12,8 @@ const ErrorPage = ({
error: Error & { digest?: string };
reset: () => void;
}) => {
+ const errorHandler = useErrorHandler();
+
useEffect(() => {
errorHandler(error);
}, [error]);
@@ -24,7 +26,7 @@ const ErrorPage = ({
flexDirection: "column",
alignItems: "center",
height: "calc(100vh - 56px)",
- gap:2
+ gap: 2,
}}
>
diff --git a/client/src/components/GlobalToast.tsx b/client/src/components/GlobalToast.tsx
index 371e31c..2931069 100644
--- a/client/src/components/GlobalToast.tsx
+++ b/client/src/components/GlobalToast.tsx
@@ -8,7 +8,11 @@ import { CheckCircle, Error, Warning } from "@mui/icons-material";
import { Snackbar, SnackbarContent, Stack } from "@mui/material";
const GlobalToast = () => {
- const { isOpen, variant, message, closeToast } = useGlobalSnackbarStore();
+ const isOpen = useGlobalSnackbarStore((store) => store.isOpen);
+ const variant = useGlobalSnackbarStore((store) => store.variant);
+ const message = useGlobalSnackbarStore((store) => store.message);
+ const closeToast = useGlobalSnackbarStore((store) => store.closeToast);
+
return (
{
switch (variant) {
case "danger":
- return ;
+ return ;
case "warning":
- return ;
+ return ;
default:
- return ;
+ return ;
}
};
diff --git a/client/src/queries/auth/useLoginMutation.tsx b/client/src/queries/auth/useLoginMutation.tsx
index 74ba379..2e0ac5a 100644
--- a/client/src/queries/auth/useLoginMutation.tsx
+++ b/client/src/queries/auth/useLoginMutation.tsx
@@ -5,8 +5,7 @@ import { useMutation, useQueryClient } from "@tanstack/react-query";
import { MyInfoQueryKeys } from "./useMyInfoQuery";
import { useRouter } from "next/navigation";
import HOME from "@/const/clientPath";
-import errorHandler from "@/utils/errorHandler";
-import { AxiosError } from "axios";
+import { useErrorHandler } from "@/utils/errorHandler";
import { useGlobalLoadingStore } from "@/store/useGlobalLoadingStore";
const useLoginMutation = () => {
@@ -14,6 +13,7 @@ const useLoginMutation = () => {
const queryClient = useQueryClient();
const router = useRouter();
const { setLoading } = useGlobalLoadingStore();
+ const errorHandler = useErrorHandler();
return useMutation({
mutationKey: LoginMuataionKey.all,
@@ -29,8 +29,7 @@ const useLoginMutation = () => {
router.refresh();
router.push(HOME);
},
- onError: (error) =>
- errorHandler(error),
+ onError: (error) => errorHandler(error),
onSettled: () => {
setLoading(false);
},
@@ -52,6 +51,7 @@ export const LoginMuataionKey = {
* @param id 유저아이디
* @returns 로그인뮤테이션 키
*/
- byId: (id: SigninRequirement["id"]) => [...LoginMuataionKey.all, {id}] as const,
+ byId: (id: SigninRequirement["id"]) =>
+ [...LoginMuataionKey.all, { id }] as const,
};
export default useLoginMutation;
diff --git a/client/src/queries/auth/useSignupMutation.tsx b/client/src/queries/auth/useSignupMutation.tsx
index 509c721..c3dd030 100644
--- a/client/src/queries/auth/useSignupMutation.tsx
+++ b/client/src/queries/auth/useSignupMutation.tsx
@@ -5,11 +5,13 @@ import { SignupRequirement } from "@/types/auth/signupRequirement";
import { useMutation } from "@tanstack/react-query";
import useLoginMutation from "./useLoginMutation";
import { useGlobalLoadingStore } from "@/store/useGlobalLoadingStore";
-import errorHandler from "@/utils/errorHandler";
+import { useErrorHandler } from "@/utils/errorHandler";
const useSignupMutation = () => {
const { mutate: loginHandler } = useLoginMutation();
const { setLoading } = useGlobalLoadingStore();
+ const errorHandler = useErrorHandler();
+
return useMutation({
mutationKey: signupMuataionKey.all,
mutationFn: async (formData: SignupRequirement) => {
diff --git a/client/src/queries/newPost/useNewPostMutation.tsx b/client/src/queries/newPost/useNewPostMutation.tsx
index 494fd88..12d066f 100644
--- a/client/src/queries/newPost/useNewPostMutation.tsx
+++ b/client/src/queries/newPost/useNewPostMutation.tsx
@@ -3,9 +3,10 @@ import axios from "@/libs/axios";
import { POST_LIST } from "@/const/serverPath";
import { NewPostRequestInterface } from "@/types/newPost/NewPostInterface";
import getTokenFromLocalStorage from "@/utils/getTokenFromLocalStorage";
-import errorHandler from "@/utils/errorHandler";
+import { useErrorHandler } from "@/utils/errorHandler";
const useNewPostMutation = () => {
+ const errorHandler = useErrorHandler();
return useMutation({
mutationFn: async (formData: NewPostRequestInterface) => {
const data = await usePostNewPostFn(formData);
diff --git a/client/src/queries/post/useDeletePostMutation.ts b/client/src/queries/post/useDeletePostMutation.ts
index 481767b..2a6cad0 100644
--- a/client/src/queries/post/useDeletePostMutation.ts
+++ b/client/src/queries/post/useDeletePostMutation.ts
@@ -2,18 +2,19 @@ import { REMOVE_POST } from "@/const/serverPath";
import { axiosPrivate } from "@/libs/axios";
import { useMutation } from "@tanstack/react-query";
import { useInvalidatePostList } from "./useGetPostListInfiniteQuery";
-import errorHandler from "@/utils/errorHandler";
+import { useErrorHandler } from "@/utils/errorHandler";
export const useDeletePostMutation = () => {
const invalidatePreviousData = useInvalidatePostList();
+ const errorHandler = useErrorHandler();
return useMutation({
mutationFn: (pk: number) => deletePostFn(pk),
onSuccess: () => {
invalidatePreviousData();
},
- onError:(err)=>{
- errorHandler(err)
- }
+ onError: (err) => {
+ errorHandler(err);
+ },
});
};
diff --git a/client/src/queries/post/useLikePostMutation.tsx b/client/src/queries/post/useLikePostMutation.tsx
index 09d6ede..f39908d 100644
--- a/client/src/queries/post/useLikePostMutation.tsx
+++ b/client/src/queries/post/useLikePostMutation.tsx
@@ -12,7 +12,7 @@ import {
} from "./useGetPostListInfiniteQuery";
import getTokenFromLocalStorage from "@/utils/getTokenFromLocalStorage";
import { POST_LIKE_URL } from "@/const/serverPath";
-import errorHandler from "@/utils/errorHandler";
+import { useErrorHandler } from "@/utils/errorHandler";
import { PostcardContextInterface } from "@/store/PostCardContext";
import { useOptimisticUpdatePostList } from "@/queries/post/updator/useOptimisticUpdatePostList";
import { useOptimisticUpdatePostDetail } from "./updator/useOptimisticUpdatePostDetail";
@@ -26,7 +26,8 @@ import { postDetailQueryKey } from "./useGetPostDetailQuery";
*/
const useLikePostMutation = (context?: PostcardContextInterface) => {
const queryClient = useQueryClient();
-
+
+ const errorHandler = useErrorHandler();
const postListUpdator = useOptimisticUpdatePostList({ type: "like" });
const postDetailUpdator = useOptimisticUpdatePostDetail({ type: "like" });
@@ -52,7 +53,7 @@ const useLikePostMutation = (context?: PostcardContextInterface) => {
);
// [디테일쿼리]
const detailQuerySnapshot = queryClient.getQueryData(
- postDetailQueryKey.byId(String(id)),
+ postDetailQueryKey.byId(String(id))
);
// Optimastic Update
// [리스트 쿼리]
diff --git a/client/src/queries/post/useUnLikePostMutation.tsx b/client/src/queries/post/useUnLikePostMutation.tsx
index ba19ac1..7a46171 100644
--- a/client/src/queries/post/useUnLikePostMutation.tsx
+++ b/client/src/queries/post/useUnLikePostMutation.tsx
@@ -12,7 +12,7 @@ import {
} from "./useGetPostListInfiniteQuery";
import getTokenFromLocalStorage from "@/utils/getTokenFromLocalStorage";
import { POST_UN_LIKE_URL } from "@/const/serverPath";
-import errorHandler from "@/utils/errorHandler";
+import { useErrorHandler } from "@/utils/errorHandler";
import { PostcardContextInterface } from "@/store/PostCardContext";
import { useOptimisticUpdatePostList } from "@/queries/post/updator/useOptimisticUpdatePostList";
import { useOptimisticUpdatePostDetail } from "./updator/useOptimisticUpdatePostDetail";
@@ -26,6 +26,7 @@ import { postDetailQueryKey } from "./useGetPostDetailQuery";
*/
const useLikePostMutation = (context?: PostcardContextInterface) => {
const queryClient = useQueryClient();
+ const errorHandler = useErrorHandler();
const postListUpdator = useOptimisticUpdatePostList({ type: "unlike" });
const postDetailUpdator = useOptimisticUpdatePostDetail({ type: "unlike" });
@@ -53,7 +54,7 @@ const useLikePostMutation = (context?: PostcardContextInterface) => {
);
// [디테일쿼리]
const detailQuerySnapshot = queryClient.getQueryData(
- postDetailQueryKey.byId(String(id)),
+ postDetailQueryKey.byId(String(id))
);
// Optimastic Update
diff --git a/client/src/queries/user/useFollowMutation.ts b/client/src/queries/user/useFollowMutation.ts
index 824eb49..027a006 100644
--- a/client/src/queries/user/useFollowMutation.ts
+++ b/client/src/queries/user/useFollowMutation.ts
@@ -6,10 +6,11 @@ import { UserInfoQueryKey } from "./useUserInfoQuery";
import { UserInfoInterface } from "@/types/user/userInfoInterface";
import { MyInfoQueryKeys } from "../auth/useMyInfoQuery";
import { MyInfoInterface } from "@/types/auth/myInfo";
-import errorHandler from "@/utils/errorHandler";
+import { useErrorHandler } from "@/utils/errorHandler";
const useFollowMutation = () => {
const queryClient = useQueryClient();
+ const errorHandler = useErrorHandler();
return useMutation({
mutationFn: async (userNo: string) => await followUserMutatuibFn(userNo),
/**
diff --git a/client/src/queries/user/useUnFollowMutation.ts b/client/src/queries/user/useUnFollowMutation.ts
index 4fc9b28..36cdc89 100644
--- a/client/src/queries/user/useUnFollowMutation.ts
+++ b/client/src/queries/user/useUnFollowMutation.ts
@@ -6,10 +6,12 @@ import { UserInfoQueryKey } from "./useUserInfoQuery";
import { UserInfoInterface } from "@/types/user/userInfoInterface";
import { MyInfoQueryKeys } from "../auth/useMyInfoQuery";
import { MyInfoInterface } from "@/types/auth/myInfo";
-import errorHandler from "@/utils/errorHandler";
+import { useErrorHandler } from "@/utils/errorHandler";
const useUnFollowMutation = () => {
const queryClient = useQueryClient();
+ const errorHandler = useErrorHandler();
+
return useMutation({
mutationFn: async (userNo: string) => await followUserMutationFn(userNo),
/**
diff --git a/client/src/store/useGlobalLoadingStore.tsx b/client/src/store/useGlobalLoadingStore.ts
similarity index 100%
rename from client/src/store/useGlobalLoadingStore.tsx
rename to client/src/store/useGlobalLoadingStore.ts
diff --git a/client/src/store/useGlobalSnackbarStore.ts b/client/src/store/useGlobalSnackbarStore.ts
index 74efec2..0552956 100644
--- a/client/src/store/useGlobalSnackbarStore.ts
+++ b/client/src/store/useGlobalSnackbarStore.ts
@@ -16,6 +16,4 @@ export const useGlobalSnackbarStore = create((set) => ({
fireToast: (message, variant = "neutral") =>
set({ isOpen: true, message, variant }),
closeToast: () => set((prev) => ({ ...prev, message: "", isOpen: false })),
-}));
-
-export const useFireToast =()=> useGlobalSnackbarStore((state)=>state.fireToast)
+}));
\ No newline at end of file
diff --git a/client/src/utils/errorHandler.ts b/client/src/utils/errorHandler.ts
index 09a1910..e4c069a 100644
--- a/client/src/utils/errorHandler.ts
+++ b/client/src/utils/errorHandler.ts
@@ -1,12 +1,24 @@
"use client";
-// import { useGlobalSnackbarStore } from "@/store/useGlobalSnackbarStore";
+import { useGlobalSnackbarStore } from "@/store/useGlobalSnackbarStore";
import { isAxiosError } from "axios";
+import { useCallback } from "react";
-export default function ErrorHandler(error: Error) {
- // const { fireToast } = useGlobalSnackbarStore();
- if (isAxiosError(error) && error.response) {
- // FIXME : Zustand 사용 연구
- // error.response.status === 401 && fireToast("로그인 후 이용 가능합니다");
- error.response.status === 401 && console.log("로그인 후 이용 가능합니다");
- }
-}
+/**
+ * Axios 에러의 status 코드를 판별해 적절한 토스트팝업을 표출해주는 함수를 리런하는 훅
+ * @returns errorHandler (error)=>void
+ */
+export const useErrorHandler = () => {
+ const fireToast = useGlobalSnackbarStore((state) => state.fireToast);
+
+ const errorHandler = useCallback((error: Error) => {
+ if (isAxiosError(error) && error.response) {
+ switch (error.response.status) {
+ case 401:
+ fireToast("로그인 후 이용 가능합니다");
+ // 토큰이 만료된 경우가 대부분이므로 토큰제거
+ localStorage.removeItem('accessToken')
+ }
+ }
+ }, []);
+ return errorHandler;
+};