diff --git a/apps/web/src/queries/likeSongQuery.ts b/apps/web/src/queries/likeSongQuery.ts index bb167da2..ee25fc1a 100644 --- a/apps/web/src/queries/likeSongQuery.ts +++ b/apps/web/src/queries/likeSongQuery.ts @@ -26,10 +26,10 @@ export function useDeleteLikeSongArrayMutation() { mutationFn: (songIds: string[]) => deleteLikeSongArray({ songIds }), onMutate: async (songIds: string[]) => { - queryClient.cancelQueries({ queryKey: ['likeSong'] }); + await queryClient.cancelQueries({ queryKey: ['likeSong'] }); const prev = queryClient.getQueryData(['likeSong']); - queryClient.setQueryData(['likeSong'], (old: PersonalSong[]) => - old.filter(song => !songIds.includes(song.song_id)), + queryClient.setQueryData(['likeSong'], (old: PersonalSong[] | undefined) => + (old ?? []).filter(song => !songIds.includes(song.song_id)), ); return { prev }; }, diff --git a/apps/web/src/queries/searchSongQuery.ts b/apps/web/src/queries/searchSongQuery.ts index 2eed3c18..f98be6e7 100644 --- a/apps/web/src/queries/searchSongQuery.ts +++ b/apps/web/src/queries/searchSongQuery.ts @@ -98,7 +98,7 @@ export const useToggleToSingMutation = (query: string, searchType: string) => { } }, onMutate: async ({ songId, method }: SongProps) => { - queryClient.cancelQueries({ queryKey: ['searchSong', query, searchType] }); + await queryClient.cancelQueries({ queryKey: ['searchSong', query, searchType] }); const prev = queryClient.getQueryData(['searchSong', query, searchType]); const isToSing = method === 'POST'; @@ -150,7 +150,7 @@ export const useToggleLikeMutation = (query: string, searchType: string) => { } }, onMutate: async ({ songId, method }: SongProps) => { - queryClient.cancelQueries({ queryKey: ['searchSong', query, searchType] }); + await queryClient.cancelQueries({ queryKey: ['searchSong', query, searchType] }); const prev = queryClient.getQueryData(['searchSong', query, searchType]); const isLike = method === 'POST'; queryClient.setQueryData( @@ -197,7 +197,7 @@ export const useSaveMutation = () => { return postSaveSong({ songId, folderName }); }, onMutate: async ({ songId, query, searchType }: FolderProps) => { - queryClient.cancelQueries({ queryKey: ['searchSong', query, searchType] }); + await queryClient.cancelQueries({ queryKey: ['searchSong', query, searchType] }); const prev = queryClient.getQueryData(['searchSong', query, searchType]); queryClient.setQueryData( diff --git a/apps/web/src/queries/tosingSongQuery.ts b/apps/web/src/queries/tosingSongQuery.ts index 18b3601b..dd6f0baa 100644 --- a/apps/web/src/queries/tosingSongQuery.ts +++ b/apps/web/src/queries/tosingSongQuery.ts @@ -8,8 +8,6 @@ import { } from '@/lib/api/tosing'; import { ToSingSong } from '@/types/song'; -// let invalidateTimeout: NodeJS.Timeout | null = null; - // 부를 노래 목록 가져오기 export function useToSingSongQuery(isAuthenticated: boolean, guestToSingSongs: ToSingSong[]) { return useQuery({ @@ -55,10 +53,10 @@ export function useDeleteToSingSongMutation() { return useMutation({ mutationFn: (songId: string) => deleteToSingSong({ songId }), onMutate: async (songId: string) => { - queryClient.cancelQueries({ queryKey: ['toSingSong'] }); + await queryClient.cancelQueries({ queryKey: ['toSingSong'] }); const prev = queryClient.getQueryData(['toSingSong']); - queryClient.setQueryData(['toSingSong'], (old: ToSingSong[]) => { - old.filter(song => song.songs.id !== songId); + queryClient.setQueryData(['toSingSong'], (old: ToSingSong[] | undefined) => { + return (old ?? []).filter(song => song.songs.id !== songId); }); return { prev }; }, @@ -68,15 +66,7 @@ export function useDeleteToSingSongMutation() { queryClient.setQueryData(['toSingSong'], context?.prev); }, onSettled: () => { - // 1초 이내에 함수가 여러 번 호출되면, 1초 뒤 트리거를 계속해서 갱신 - // if (invalidateTimeout) { - // clearTimeout(invalidateTimeout); - // } - // invalidateTimeout = setTimeout(() => { - // queryClient.invalidateQueries({ queryKey: ['toSingSong'] }); - // }, 1000); queryClient.invalidateQueries({ queryKey: ['searchSong'] }); - queryClient.invalidateQueries({ queryKey: ['toSingSong'] }); }, }); } @@ -94,11 +84,14 @@ export function usePatchToSingSongMutation() { newWeight: number; newItems: ToSingSong[]; }) => patchToSingSong({ songId, newWeight }), - onMutate: async ({ newItems }) => { - queryClient.cancelQueries({ queryKey: ['toSingSong'] }); + onMutate: async ({ songId, newWeight, newItems }) => { + await queryClient.cancelQueries({ queryKey: ['toSingSong'] }); const prev = queryClient.getQueryData(['toSingSong']); - // newItems으로 전체 쿼리 교체 - queryClient.setQueryData(['toSingSong'], newItems); + // 이동된 항목의 order_weight를 newWeight로 반영해 stale 방지 + const optimisticItems = newItems.map(item => + item.songs.id === songId ? { ...item, order_weight: newWeight } : item, + ); + queryClient.setQueryData(['toSingSong'], optimisticItems); return { prev }; }, onError: (error, variables, context) => { @@ -106,8 +99,5 @@ export function usePatchToSingSongMutation() { alert(error.message ?? 'PATCH 실패'); queryClient.setQueryData(['toSingSong'], context?.prev); }, - onSettled: () => { - queryClient.invalidateQueries({ queryKey: ['toSingSong'] }); - }, }); }