Skip to content

Commit

Permalink
Refactor: useMutation Keys 관리
Browse files Browse the repository at this point in the history
파일에 관리 및 간단 제공자 사용
  • Loading branch information
jihostudy committed Oct 4, 2024
1 parent 57e72c9 commit af05533
Show file tree
Hide file tree
Showing 21 changed files with 465 additions and 344 deletions.
2 changes: 1 addition & 1 deletion app/(route)/(header)/community/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import React, { ReactNode, useEffect } from 'react'

import { INITIAL_PLAN } from '@/lib/constants/dummy_data'
import usePlanStore from '@/lib/context/planStore'
import { queryClient } from '@/lib/HTTP/http'
import { queryClient } from '@/lib/HTTP/cacheKey'

interface CommunityLayoutProps {
children: React.ReactNode
Expand Down
2 changes: 1 addition & 1 deletion app/(route)/(header)/main/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { ToastProvider } from '@/components/ui/toast'
import { Toaster } from '@/components/ui/toaster'
import { INITIAL_PLAN } from '@/lib/constants/dummy_data'
import usePlanStore from '@/lib/context/planStore'
import { queryClient } from '@/lib/HTTP/http'
import { queryClient } from '@/lib/HTTP/cacheKey'

interface MainLayoutProps {
children: React.ReactNode
Expand Down
2 changes: 1 addition & 1 deletion app/(route)/(header)/plan/detail/[id]/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { useEffect } from 'react'
import { Toaster } from '@/components/ui/toaster'
import { INITIAL_PLAN } from '@/lib/constants/dummy_data'
import usePlanStore from '@/lib/context/planStore'
import { queryClient } from '@/lib/HTTP/http'
import { queryClient } from '@/lib/HTTP/cacheKey'

export default function PlanDetailsLayout({ children }: Readonly<{ children: React.ReactNode }>) {
const { setPlanData } = usePlanStore()
Expand Down
6 changes: 3 additions & 3 deletions app/(route)/(header)/plan/detail/[id]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import Comments from '@/components/plan/details/Comments'
import Description from '@/components/plan/details/Description'
import PlanDetailSchedule from '@/components/plan/details/Schedule'
import useDropdownStore from '@/lib/context/dropdownStore'
import { fetchPlan } from '@/lib/HTTP/plan/API'
import { getPlan } from '@/lib/HTTP/plan/API'
import { CommentResponse } from '@/lib/types/Entity/comment'
import { Plan } from '@/lib/types/Entity/plan'
import { scrollToTop } from '@/lib/utils/scroll'
Expand All @@ -36,7 +36,7 @@ const PlanDetailsPage = ({ params }: PlanDetailsPageProps): ReactNode => {
// #0. Fetch Plan & User Info using planId & userId (useQuery)
const { data, isPending, isError, error } = useQuery({
queryKey: ['plan', planId],
queryFn: () => fetchPlan({ planId: planId, accessToken: session.data ? session.data.accessToken : null }),
queryFn: () => getPlan({ planId: planId, accessToken: session.data ? session.data.accessToken : null }),
enabled: session.data !== undefined,
})

Expand All @@ -50,7 +50,7 @@ const PlanDetailsPage = ({ params }: PlanDetailsPageProps): ReactNode => {
content = <LoadingPage />
}
if (data) {
console.log('Fetched Data from fetchPlan: ', data)
console.log('Fetched Data from getPlan: ', data)

content = (
<div className='relative flex w-4/5 max-w-[1400px] flex-col items-start justify-start'>
Expand Down
2 changes: 1 addition & 1 deletion app/(route)/plan/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import React, { ReactNode, Suspense } from 'react'
import PlanSideBar from '@/components/plan/PlanSideBar'
import { ToastProvider } from '@/components/ui/toast'
import { Toaster } from '@/components/ui/toaster'
import { queryClient } from '@/lib/HTTP/http'
import { queryClient } from '@/lib/HTTP/cacheKey'

interface MainLayoutProps {
children: React.ReactNode
Expand Down
4 changes: 2 additions & 2 deletions app/(route)/plan/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import LoadingPage from '@/components/common/LoadingPage'
import UpdateInfo from '@/components/plan/UpdateInfo'
import UpdatePeriod from '@/components/plan/UpdatePeriod'
import usePlanStore from '@/lib/context/planStore'
import { fetchPlan } from '@/lib/HTTP/plan/API'
import { getPlan } from '@/lib/HTTP/plan/API'
interface TravelInfoPageProps {}

const TravelInfoPage = ({}: TravelInfoPageProps): ReactNode => {
Expand All @@ -28,7 +28,7 @@ const TravelInfoPage = ({}: TravelInfoPageProps): ReactNode => {
// #0. Fetch Plan & User Info using planId & userId (useQuery)
const { data, isPending, isError, error } = useQuery({
queryKey: ['plan', planId],
queryFn: () => fetchPlan({ planId: planId, accessToken: session.data ? session.data.accessToken : null }),
queryFn: () => getPlan({ planId: planId, accessToken: session.data ? session.data.accessToken : null }),
enabled: planId !== -1 && planId !== planData.id,
//select는 data가 존재할때만 호출된다. 그렇기때문에 data가 undefined인 경우를 고려할 필요가 없다.
select: data => data.planData,
Expand Down
2 changes: 1 addition & 1 deletion components/main/Contents.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { useSession } from 'next-auth/react'
import React, { ReactNode, useEffect, useRef, useState } from 'react'

import { ROUTES } from '@/lib/constants/routes'
import { queryClient } from '@/lib/HTTP/http'
import { queryClient } from '@/lib/HTTP/cacheKey'
import { fetchPlaces, PlaceCardType } from '@/lib/HTTP/places/API'
import { fetchPlans, PlanCardType } from '@/lib/HTTP/plans/API'
import LucideIcon from '@/lib/icons/LucideIcon'
Expand Down
20 changes: 4 additions & 16 deletions components/main/MainPlaceCard.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
'use client'
import { useMutation } from '@tanstack/react-query'
import Image from 'next/image'
import React, { ReactNode, useState } from 'react'

import { PLAN_DEFAULT_IMAGE } from '@/lib/constants/dummy_data'
import { ClientModalData } from '@/lib/constants/errors'
import { NO_REVIEW_TEXT } from '@/lib/constants/no_data'
import { queryClient } from '@/lib/HTTP/http'
import { placeDeleteScrap } from '@/lib/HTTP/place/API'
import { useMutationStore } from '@/lib/HTTP/cacheKey'
import { DeletePlaceScrapType } from '@/lib/HTTP/place/API'
import { PlaceCardType } from '@/lib/HTTP/places/API'
import LucideIcon from '@/lib/icons/LucideIcon'
import useModal from '@/lib/utils/hooks/useModal'
Expand Down Expand Up @@ -84,6 +83,7 @@ const Menu = ({ id, setIsDeleted, user }: MenuProps) => {
const { ref, isOpen, toggleDropdown } = useDropdown() // 드롭다운 상태 관리
const { modalData, handleModalStates, Modal, isOpen: isModalOpen } = useModal()

const { mutate: deletePlanMutate } = useMutationStore<DeletePlaceScrapType>(['deletePlaceScrap'])
// Todo: 리뷰삭제 및 쓰기 API 연결
const options = [
{
Expand All @@ -97,18 +97,6 @@ const Menu = ({ id, setIsDeleted, user }: MenuProps) => {
},
]

/**
* 스크랩 삭제하기
*/
const { mutate } = useMutation({
mutationKey: ['place', 'scrap', { placeId: id }],
mutationFn: placeDeleteScrap,

onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['places', 'scrap'] })
},
})

const deleteScrapHandler = () => {
toggleDropdown() // 드롭다운 닫기
handleModalStates(ClientModalData.deleteScrap, 'open')
Expand All @@ -122,7 +110,7 @@ const Menu = ({ id, setIsDeleted, user }: MenuProps) => {
if (modalData.id === 'confirm') {
switch (modalData) {
case ClientModalData.deleteScrap:
mutate(
deletePlanMutate(
{ placeId: id, accessToken: user.accessToken },
{
onSuccess: () => {
Expand Down
114 changes: 52 additions & 62 deletions components/plan/Cards.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
'use client'
import { useMutation } from '@tanstack/react-query'
import Image from 'next/image'
import { useRouter } from 'next/navigation'
import { useSession } from 'next-auth/react'
import React, { ReactNode, useEffect, useState } from 'react'
import React, { ReactNode, useState } from 'react'

import { PLACE_DEFAULT_IMAGE, PLAN_DEFAULT_IMAGE } from '@/lib/constants/dummy_data'
import { ClientModalData } from '@/lib/constants/errors'
import { NO_PLAN_TITLE, NO_REVIEW_TEXT, NO_TAGS, NO_USER_DESCRIPTION } from '@/lib/constants/no_data'
import { ROUTES } from '@/lib/constants/routes'
import useMapStore from '@/lib/context/mapStore'
import { queryClient } from '@/lib/HTTP/http'
import { placeAddScrap, placeDeleteScrap } from '@/lib/HTTP/place/API'
import { useMutationStore } from '@/lib/HTTP/cacheKey'
import { AddPlaceScrapType, DeletePlaceScrapType } from '@/lib/HTTP/place/API'
import { PlaceCardType } from '@/lib/HTTP/places/API'
import { planAddLikes, planAddScrap, planDeleteLikes, planDeleteScrap } from '@/lib/HTTP/plan/API'
import { AddPlanLikesType, AddPlanScrapType, DeletePlanLikesType, DeletePlanScrapType } from '@/lib/HTTP/plan/API'
import { PlanCardType } from '@/lib/HTTP/plans/API'
import LucideIcon from '@/lib/icons/LucideIcon'
import { Place } from '@/lib/types/Entity/place'
Expand Down Expand Up @@ -119,37 +118,29 @@ export const PlaceCard = ({ data, focusedPlaceCard, handleClickCard }: PlaceCard
const session: any = useSession()

const [tmpIsScrap, setTmpIsScrap] = useState<boolean>(isScraped)

const { mutate: scrapPlaceMutate } = useMutationStore<AddPlaceScrapType | DeletePlaceScrapType>(
!tmpIsScrap ? ['addPlaceScrap'] : ['deletePlaceScrap'],
)

const focusHandler = () => {
handleClickCard(data)
}
// scrap
const scrapHandler = () => {
mutate({ placeId: data.id, accessToken: session.data.accessToken })
scrapPlaceMutate(
{ placeId: data.id, accessToken: session.data.accessToken },
{
onSuccess: () => {
setTmpIsScrap(prev => !prev)
},
onError: () => {
setTmpIsScrap(prev => !prev)
},
},
)
}

/**
* 스크랩하기 및 삭제하기
*/
const { mutate } = useMutation({
mutationKey: ['place', 'scrap', { placeId: data.id }],
mutationFn: !tmpIsScrap ? placeAddScrap : placeDeleteScrap,
onSuccess: () => {
setTmpIsScrap(prev => !prev)
toast({ title: '변경되었습니다!' })
},
onError: () => {
toast({ title: '다시 시도해주세요!' })
setTmpIsScrap(prev => !prev)
},
onSettled: () => {
queryClient.invalidateQueries({ queryKey: ['places', 'search'] })
},
})

useEffect(() => {
console.log(tmpIsScrap)
}, [tmpIsScrap])

return (
<div
onClick={focusHandler}
Expand Down Expand Up @@ -221,6 +212,8 @@ export const PlanCard = ({ data, handleClickCard }: PlanCardProps) => {
const { modalData, handleModalStates, Modal } = useModal()

const { id, imgSrc, title, likeCnt, scrapCnt, description, commentCnt, tags, isScraped, isLiked } = data

// 임시 반영을 위한
const [tmpLikeData, setTmpLikeData] = useState({
likeCnt: likeCnt,
isLiked: isLiked,
Expand All @@ -231,22 +224,13 @@ export const PlanCard = ({ data, handleClickCard }: PlanCardProps) => {
})

// #1. Plan Likes Mutation
const { mutate: likesMutate, isPending: isLikesPending } = useMutation({
mutationKey: ['plan', { planId: id }],
mutationFn: !tmpLikeData.isLiked ? planAddLikes : planDeleteLikes,
onError: error => {
setTmpLikeData(prev => ({
likeCnt: !tmpLikeData.isLiked ? (prev.likeCnt -= 1) : (prev.likeCnt += 1),
isLiked: !prev.isLiked,
}))
toast({ title: '서버 오류 다시 시도해주세요' })
},

onSettled: () => {
queryClient.invalidateQueries({ queryKey: ['plan', { planId: id }] })
queryClient.invalidateQueries({ queryKey: ['plans'] })
},
})
const { mutate: likesMutate, isPending: isLikesPending } = useMutationStore<AddPlanLikesType | DeletePlanLikesType>(
!tmpLikeData.isLiked ? ['addPlanLikes'] : ['deletePlanLikes'],
)
// #2. Plan Scrap Mutations
const { mutate: scrapPlaceMutate, isPending: isScrapPending } = useMutationStore<
AddPlanScrapType | DeletePlanScrapType
>(!tmpScrapData.isScraped ? ['addPlanScrap'] : ['deletePlanScrap'])

const likeHandler = () => {
if (isLikesPending) {
Expand All @@ -261,24 +245,20 @@ export const PlanCard = ({ data, handleClickCard }: PlanCardProps) => {
likeCnt: !tmpLikeData.isLiked ? (prev.likeCnt += 1) : (prev.likeCnt -= 1),
isLiked: !prev.isLiked,
}))
likesMutate({ planId: id, accessToken: session.data.accessToken })
likesMutate(
{ planId: id, accessToken: session.data.accessToken },
{
onError: error => {
setTmpLikeData(prev => ({
likeCnt: !tmpLikeData.isLiked ? (prev.likeCnt -= 1) : (prev.likeCnt += 1),
isLiked: !prev.isLiked,
}))
toast({ title: '서버 오류 다시 시도해주세요' })
},
},
)
}

// #1. Plan Scrap Mutations
const { mutate: scrapMutate, isPending: isScrapPending } = useMutation({
mutationKey: ['plan', { planId: id }],
mutationFn: !tmpScrapData.isScraped ? planAddScrap : planDeleteScrap,
onError: () => {
setTmpScrapData(prev => ({
scrapCnt: !tmpScrapData.isScraped ? (prev.scrapCnt -= 1) : (prev.scrapCnt += 1),
isScraped: !prev.isScraped,
}))
},
onSettled: () => {
queryClient.invalidateQueries({ queryKey: ['plan', { planId: id }] })
queryClient.invalidateQueries({ queryKey: ['plans'] })
},
})
const scrapHandler = () => {
if (isScrapPending) {
toast({ title: '다른 작업 수행중입니다.' })
Expand All @@ -292,7 +272,17 @@ export const PlanCard = ({ data, handleClickCard }: PlanCardProps) => {
scrapCnt: !tmpScrapData.isScraped ? (prev.scrapCnt += 1) : (prev.scrapCnt -= 1),
isScraped: !prev.isScraped,
}))
scrapMutate({ planId: id, accessToken: session.data.accessToken })
scrapPlaceMutate(
{ planId: id, accessToken: session.data.accessToken },
{
onError: () => {
setTmpScrapData(prev => ({
scrapCnt: !tmpScrapData.isScraped ? (prev.scrapCnt -= 1) : (prev.scrapCnt += 1),
isScraped: !prev.isScraped,
}))
},
},
)
}

const onConfirm = () => {
Expand Down
4 changes: 2 additions & 2 deletions components/plan/PlanSchedule.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import React, { ReactNode, useEffect, useState } from 'react'
import { INITIAL_PLAN } from '@/lib/constants/dummy_data'
import useMapStore from '@/lib/context/mapStore'
import usePlanStore from '@/lib/context/planStore'
import { fetchPlan } from '@/lib/HTTP/plan/API'
import { getPlan } from '@/lib/HTTP/plan/API'
import { PlanCardType } from '@/lib/HTTP/plans/API'
import LucideIcon from '@/lib/icons/LucideIcon'
import { bounce } from '@/lib/types/animation'
Expand Down Expand Up @@ -37,7 +37,7 @@ const PlanSchedule = ({ id, plan, setFocusPlanCard, className }: PlanSchedulePro
// #0. Fetch Plan & User Info using planId & userId (useQuery)
const { data, isFetching, isError, error } = useQuery({
queryKey: ['plan', plan.id],
queryFn: () => fetchPlan({ planId: plan.id, accessToken: session.data ? session.data.accessToken : null }),
queryFn: () => getPlan({ planId: plan.id, accessToken: session.data ? session.data.accessToken : null }),
enabled: id === 'scrap',
})

Expand Down
Loading

0 comments on commit af05533

Please sign in to comment.