diff --git a/frontend/src/hooks/query/useHeaderProfile.ts b/frontend/src/hooks/query/useHeaderProfile.ts index e191ab93e..54f0bea2a 100644 --- a/frontend/src/hooks/query/useHeaderProfile.ts +++ b/frontend/src/hooks/query/useHeaderProfile.ts @@ -27,6 +27,6 @@ export const useHeaderProfile = () => { }, [queryResult.error]); return { - data: queryResult.data as NonNullable, + data: queryResult.data, }; }; diff --git a/frontend/src/hooks/query/useMyGithubUrl.ts b/frontend/src/hooks/query/useMyGithubUrl.ts index 0e9e0fdb9..597e423c9 100644 --- a/frontend/src/hooks/query/useMyGithubUrl.ts +++ b/frontend/src/hooks/query/useMyGithubUrl.ts @@ -24,6 +24,6 @@ export const useMyGithubUrl = () => { }, [queryResult.error]); return { - data: queryResult.data as NonNullable, + data: queryResult.data, }; }; diff --git a/frontend/src/hooks/query/useMyPostList.ts b/frontend/src/hooks/query/useMyPostList.ts index 7ec8d7b91..95d6f8b27 100644 --- a/frontend/src/hooks/query/useMyPostList.ts +++ b/frontend/src/hooks/query/useMyPostList.ts @@ -4,7 +4,7 @@ import { ToastContext } from '@/contexts/ToastContext'; import { APIError } from '@/types/error'; import { GetMyPagePostResponse, MyPagePost } from '@/types/myPage'; import { ReviewStatus } from '@/types/runnerPost'; -import { useInfiniteQuery, useSuspenseInfiniteQuery } from '@tanstack/react-query'; +import { useInfiniteQuery } from '@tanstack/react-query'; import { useContext, useEffect } from 'react'; const PAGE_SIZE = 10; @@ -51,6 +51,6 @@ export const useMyPostList = (isRunner: boolean, reviewStatus?: ReviewStatus) => return { ...queryResult, - data: queryResult.data as NonNullable, + data: queryResult.data ?? [], }; }; diff --git a/frontend/src/hooks/query/useMyRunnerProfile.ts b/frontend/src/hooks/query/useMyRunnerProfile.ts index 24c3ababc..41d499f97 100644 --- a/frontend/src/hooks/query/useMyRunnerProfile.ts +++ b/frontend/src/hooks/query/useMyRunnerProfile.ts @@ -21,6 +21,6 @@ export const useMyRunnerProfile = () => { }, [queryResult.error]); return { - data: queryResult.data as NonNullable, + data: queryResult.data, }; }; diff --git a/frontend/src/hooks/query/useMySupporterProfile.ts b/frontend/src/hooks/query/useMySupporterProfile.ts index 5ad86e8e8..96a9eb1d1 100644 --- a/frontend/src/hooks/query/useMySupporterProfile.ts +++ b/frontend/src/hooks/query/useMySupporterProfile.ts @@ -21,6 +21,6 @@ export const useMySupporterProfile = () => { }, [queryResult.error]); return { - data: queryResult.data as NonNullable, + data: queryResult.data, }; }; diff --git a/frontend/src/hooks/query/useNotification.ts b/frontend/src/hooks/query/useNotification.ts index f89fbab6f..0e7b5c136 100644 --- a/frontend/src/hooks/query/useNotification.ts +++ b/frontend/src/hooks/query/useNotification.ts @@ -11,6 +11,6 @@ export const useNotification = () => { }); return { - data: queryResult.data as NonNullable, + data: queryResult.data, }; }; diff --git a/frontend/src/hooks/query/useOtherRunnerProfile.ts b/frontend/src/hooks/query/useOtherRunnerProfile.ts index 76607810a..66075e814 100644 --- a/frontend/src/hooks/query/useOtherRunnerProfile.ts +++ b/frontend/src/hooks/query/useOtherRunnerProfile.ts @@ -21,6 +21,6 @@ export const useOtherRunnerProfile = (userId: number) => { }, [queryResult.error]); return { - data: queryResult.data as NonNullable, + data: queryResult.data, }; }; diff --git a/frontend/src/hooks/query/useOtherSupporterPost.ts b/frontend/src/hooks/query/useOtherSupporterPost.ts index e9f34bf38..90bb104cd 100644 --- a/frontend/src/hooks/query/useOtherSupporterPost.ts +++ b/frontend/src/hooks/query/useOtherSupporterPost.ts @@ -35,6 +35,6 @@ export const useOtherSupporterPost = (userId: number) => { return { ...queryResult, - data: queryResult.data as NonNullable, + data: queryResult.data, }; }; diff --git a/frontend/src/hooks/query/useOtherSupporterPostCount.ts b/frontend/src/hooks/query/useOtherSupporterPostCount.ts index 10bbadd9c..2e1a45dc3 100644 --- a/frontend/src/hooks/query/useOtherSupporterPostCount.ts +++ b/frontend/src/hooks/query/useOtherSupporterPostCount.ts @@ -10,6 +10,6 @@ export const useOtherSupporterPostCount = (supporterId: number) => { }); return { - data: queryResult.data as NonNullable, + data: queryResult.data, }; }; diff --git a/frontend/src/hooks/query/useOtherSupporterProfile.ts b/frontend/src/hooks/query/useOtherSupporterProfile.ts index 46e1c5d43..e45c47aea 100644 --- a/frontend/src/hooks/query/useOtherSupporterProfile.ts +++ b/frontend/src/hooks/query/useOtherSupporterProfile.ts @@ -21,6 +21,6 @@ export const useOtherSupporterProfile = (userId: number) => { }, [queryResult.error]); return { - data: queryResult.data as NonNullable, + data: queryResult.data, }; }; diff --git a/frontend/src/hooks/query/useProposedSupporterList.ts b/frontend/src/hooks/query/useProposedSupporterList.ts index 6bd0416af..a7ff80cac 100644 --- a/frontend/src/hooks/query/useProposedSupporterList.ts +++ b/frontend/src/hooks/query/useProposedSupporterList.ts @@ -21,6 +21,6 @@ export const useProposedSupporterList = (runnerPostId: number) => { }, [queryResult.error]); return { - data: queryResult.data as NonNullable, + data: queryResult.data, }; }; diff --git a/frontend/src/hooks/query/useReviewCancelation.ts b/frontend/src/hooks/query/useReviewCancelation.ts index 18ceeedff..23c7c6ee3 100644 --- a/frontend/src/hooks/query/useReviewCancelation.ts +++ b/frontend/src/hooks/query/useReviewCancelation.ts @@ -1,10 +1,11 @@ import { useContext } from 'react'; import { ToastContext } from '@/contexts/ToastContext'; -import { useMutation } from '@tanstack/react-query'; +import { InfiniteData, useMutation } from '@tanstack/react-query'; import { APIError } from '@/types/error'; import { patchReviewCancelation } from '@/apis/apis'; import { ERROR_TITLE, TOAST_COMPLETION_MESSAGE } from '@/constants/message'; import { queryClient } from './queryClient'; +import { GetMyPagePostResponse } from '@/types/myPage'; export const useReviewCancelation = () => { const { showErrorToast, showCompletionToast } = useContext(ToastContext); @@ -12,14 +13,38 @@ export const useReviewCancelation = () => { const queryResult = useMutation({ mutationFn: (runnerPostId: number) => patchReviewCancelation(runnerPostId), + onMutate: async (deletedPostId: number) => { + await queryClient.cancelQueries({ queryKey: ['mySupporterPost', 'NOT_STARTED'] }); + + const previous = queryClient.getQueryData(['mySupporterPost', 'NOT_STARTED']); + + queryClient.setQueryData>(['mySupporterPost', 'NOT_STARTED'], (oldData) => { + if (!oldData) return undefined; + + const newData = oldData.pages.map((page) => { + return { ...page, data: page.data.filter((item) => item.runnerPostId !== deletedPostId) }; + }); + + return { + ...oldData, + pages: newData, + }; + }); + + return { previous }; + }, + onSuccess: () => { showCompletionToast(TOAST_COMPLETION_MESSAGE.REVIEW_CANCEL); - queryClient.refetchQueries({ queryKey: ['mySupporterPost', 'NOT_STARTED'] }); }, onError: () => { showErrorToast({ title: ERROR_TITLE.REQUEST, description: '리뷰 취소 요청이 실패했어요' }); }, + + onSettled: () => { + queryClient.invalidateQueries({ queryKey: ['mySupporterPost', 'NOT_STARTED'] }); + }, }); return queryResult; diff --git a/frontend/src/hooks/query/useReviewComplete.ts b/frontend/src/hooks/query/useReviewComplete.ts index e44453ed1..4927e4fdd 100644 --- a/frontend/src/hooks/query/useReviewComplete.ts +++ b/frontend/src/hooks/query/useReviewComplete.ts @@ -1,10 +1,11 @@ import { useContext } from 'react'; import { ToastContext } from '@/contexts/ToastContext'; -import { useMutation } from '@tanstack/react-query'; +import { InfiniteData, useMutation } from '@tanstack/react-query'; import { APIError } from '@/types/error'; import { patchReviewComplete } from '@/apis/apis'; import { ERROR_TITLE, TOAST_COMPLETION_MESSAGE } from '@/constants/message'; import { queryClient } from './queryClient'; +import { GetMyPagePostResponse } from '@/types/myPage'; export const useReviewComplete = () => { const { showErrorToast, showCompletionToast } = useContext(ToastContext); @@ -12,15 +13,39 @@ export const useReviewComplete = () => { const queryResult = useMutation({ mutationFn: (runnerPostId: number) => patchReviewComplete(runnerPostId), + onMutate: async (deletedPostId: number) => { + await queryClient.cancelQueries({ queryKey: ['mySupporterPost', 'IN_PROGRESS'] }); + + const previous = queryClient.getQueryData(['mySupporterPost', 'IN_PROGRESS']); + + queryClient.setQueryData>(['mySupporterPost', 'IN_PROGRESS'], (oldData) => { + if (!oldData) return undefined; + + const newData = oldData.pages.map((page) => { + return { ...page, data: page.data.filter((item) => item.runnerPostId !== deletedPostId) }; + }); + + return { + ...oldData, + pages: newData, + }; + }); + + return { previous }; + }, + onSuccess: () => { showCompletionToast(TOAST_COMPLETION_MESSAGE.REVIEW_COMPLETE); - queryClient.refetchQueries({ queryKey: ['mySupporterPost', 'IN_PROGRESS'] }); - queryClient.refetchQueries({ queryKey: ['mySupporterPost', 'DONE'] }); }, onError: () => { showErrorToast({ title: ERROR_TITLE.REQUEST, description: '리뷰 완료 요청이 실패했어요' }); }, + + onSettled: () => { + queryClient.invalidateQueries({ queryKey: ['mySupporterPost', 'IN_PROGRESS'] }); + queryClient.invalidateQueries({ queryKey: ['mySupporterPost', 'DONE'] }); + }, }); return queryResult; diff --git a/frontend/src/hooks/query/useRunnerPostDetail.ts b/frontend/src/hooks/query/useRunnerPostDetail.ts index 7dc50df02..49bd91d52 100644 --- a/frontend/src/hooks/query/useRunnerPostDetail.ts +++ b/frontend/src/hooks/query/useRunnerPostDetail.ts @@ -21,6 +21,6 @@ export const useRunnerPostDetail = (runnerPostId: number, isLogin: boolean) => { }, [queryResult.error]); return { - data: queryResult.data as NonNullable, + data: queryResult.data, }; }; diff --git a/frontend/src/hooks/query/useRunnerPostList.ts b/frontend/src/hooks/query/useRunnerPostList.ts index f89fcce52..dec74acbc 100644 --- a/frontend/src/hooks/query/useRunnerPostList.ts +++ b/frontend/src/hooks/query/useRunnerPostList.ts @@ -43,6 +43,6 @@ export const useRunnerPostList = (reviewStatus: ReviewStatus | null, tagName?: s return { ...queryResult, - data: queryResult.data as NonNullable, + data: queryResult.data ?? [], }; }; diff --git a/frontend/src/hooks/query/useSearchTag.ts b/frontend/src/hooks/query/useSearchTag.ts index 03f0d2f75..4283b6d07 100644 --- a/frontend/src/hooks/query/useSearchTag.ts +++ b/frontend/src/hooks/query/useSearchTag.ts @@ -8,6 +8,6 @@ export const useSearchTag = (keyword: string) => { }); return { - data: queryResult.data as NonNullable, + data: queryResult.data, }; }; diff --git a/frontend/src/hooks/query/useSelectionSupporter.ts b/frontend/src/hooks/query/useSelectionSupporter.ts index d17948f76..e1c4c0218 100644 --- a/frontend/src/hooks/query/useSelectionSupporter.ts +++ b/frontend/src/hooks/query/useSelectionSupporter.ts @@ -22,6 +22,7 @@ export const useSelectionSupporter = () => { onSuccess: () => { showCompletionToast(TOAST_COMPLETION_MESSAGE.SUPPORTER_SELECT); queryClient.invalidateQueries({ queryKey: ['myRunnerPost', 'IN_PROGRESS'] }); + queryClient.invalidateQueries({ queryKey: ['myRunnerPost', 'NOT_STARTED'] }); goToRunnerMyPage(); }, diff --git a/frontend/src/pages/RunnerMyPage.tsx b/frontend/src/pages/RunnerMyPage.tsx index 81154f98f..923eb8783 100644 --- a/frontend/src/pages/RunnerMyPage.tsx +++ b/frontend/src/pages/RunnerMyPage.tsx @@ -99,7 +99,7 @@ const RunnerMyPage = () => { fontSize={isMobile ? '16px' : '26px'} /> - + {hasNextPage && (