From 21b749cf1221549bc56dde8c5ebdbf026eb31ed4 Mon Sep 17 00:00:00 2001 From: hee-suh Date: Fri, 4 Oct 2024 20:47:54 +0900 Subject: [PATCH 1/3] fix: revalidate server actions using revalidateTag --- src/app/actions.ts | 7 ++++++- .../map/[mapId]/place-list-bottom-sheet.tsx | 6 ++++-- src/app/place/[placeId]/layout.tsx | 7 ++++++- src/app/place/[placeId]/place-box.tsx | 18 ++++++++++-------- .../place/[placeId]/register/register-box.tsx | 4 +++- src/app/profile/[mapId]/[id]/place-item.tsx | 7 ++++--- .../search/[query]/result-place-map-popup.tsx | 7 ++++--- src/app/search/[query]/result-search-list.tsx | 7 ++++--- src/components/place/place-map-popup.tsx | 7 ++++--- src/utils/api/index.ts | 5 ++++- 10 files changed, 49 insertions(+), 26 deletions(-) diff --git a/src/app/actions.ts b/src/app/actions.ts index 1bd0c900..3fd1f004 100644 --- a/src/app/actions.ts +++ b/src/app/actions.ts @@ -1,6 +1,7 @@ 'use server' import { cookies } from 'next/headers' +import { revalidatePath, revalidateTag } from 'next/cache' const setCookie = async (name: string, value: string) => { cookies().set(name, value) @@ -10,4 +11,8 @@ const deleteCookie = async (name: string) => { cookies().delete(name) } -export { setCookie, deleteCookie } +const revalidatePlaces = async (mapId: string) => { + revalidateTag(`places-${mapId}`) +} + +export { setCookie, deleteCookie, revalidatePlaces } diff --git a/src/app/map/[mapId]/place-list-bottom-sheet.tsx b/src/app/map/[mapId]/place-list-bottom-sheet.tsx index ad21055b..eb4644f2 100644 --- a/src/app/map/[mapId]/place-list-bottom-sheet.tsx +++ b/src/app/map/[mapId]/place-list-bottom-sheet.tsx @@ -13,6 +13,7 @@ import { APIError } from '@/models/api/index' import type { PlaceType } from '@/models/api/place' import { useInfiniteScroll } from '@/hooks/use-infinite-scroll' import { api } from '@/utils/api' +import { revalidatePlaces } from '@/app/actions' interface PlaceListBottomSheetProps { places: PlaceType[] | null @@ -36,10 +37,11 @@ const PlaceListBottomSheet = forwardRef< itemsPerPage: 10, }) - const { data: user, revalidate } = useFetch(api.users.me.get, { + const { data: user } = useFetch(api.users.me.get, { key: ['user'], }) const userId = user?.id + const numOfSelectedFilter = (selectedFilter?.category !== 'all' ? 1 : 0) + (selectedFilter?.tags.length ?? 0) @@ -77,7 +79,7 @@ const PlaceListBottomSheet = forwardRef< placeId: place.place.id, }) } - revalidate(['places', mapId]) + revalidatePlaces(mapId) } catch (error) { if (error instanceof APIError) { notify.error(error.message) diff --git a/src/app/place/[placeId]/layout.tsx b/src/app/place/[placeId]/layout.tsx index e5e0330f..7a776c0f 100644 --- a/src/app/place/[placeId]/layout.tsx +++ b/src/app/place/[placeId]/layout.tsx @@ -1,12 +1,17 @@ 'use client' import type { ReactNode } from 'react' -import { useRouter } from 'next/navigation' +import { usePathname, useRouter } from 'next/navigation' import AccessibleIconButton from '@/components/common/accessible-icon-button' const PlaceDetailLayout = ({ children }: { children: ReactNode }) => { const router = useRouter() + const pathname = usePathname() + + if (pathname.includes('register')) { + return <>{children} + } return (
diff --git a/src/app/place/[placeId]/place-box.tsx b/src/app/place/[placeId]/place-box.tsx index fa7760ba..a4801d0f 100644 --- a/src/app/place/[placeId]/place-box.tsx +++ b/src/app/place/[placeId]/place-box.tsx @@ -25,6 +25,7 @@ import { roundToNthDecimal } from '@/utils/number' import { allowUserPositionStorage } from '@/utils/storage' import cn from '@/utils/cn' import { sendGAEvent } from '@next/third-parties/google' +import { revalidatePlaces } from '@/app/actions' interface PlaceBoxProps { place: PlaceDetail @@ -40,7 +41,7 @@ const PlaceBox = ({ place, mapId }: PlaceBoxProps) => { const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false) const [isRecentlyLike, setIsRecentlyLike] = useState(null) const router = useSafeRouter() - const [isAlreadyPick, setIsAlreadyPick] = useState(place.isRegisteredPlace) + const isAlreadyPick = place.isRegisteredPlace const { userLocation } = useUserGeoLocation() const isAllowPosition = allowUserPositionStorage.getValueOrNull() const diffDistance = getDistance( @@ -50,10 +51,9 @@ const PlaceBox = ({ place, mapId }: PlaceBoxProps) => { place.x, ) - const { data: user, revalidate } = useFetch(api.users.me.get, { + const { data: user } = useFetch(api.users.me.get, { key: ['user'], }) - const { data: mapInfo, isFetching } = useFetch(() => api.maps.id.get(mapId), { enabled: !!mapId, }) @@ -76,6 +76,10 @@ const PlaceBox = ({ place, mapId }: PlaceBoxProps) => { return likedUserCount + recentlyLikedBonus })() + useEffect(() => { + router.refresh() + }, [router]) + useEffect(() => { if (!place || !user) return setIsLikePlace( @@ -93,7 +97,7 @@ const PlaceBox = ({ place, mapId }: PlaceBoxProps) => { placeId: place.id, mapId, }) - revalidate(['places', mapId]) + revalidatePlaces(mapId) } catch (error) { setIsLikePlace(false) setIsRecentlyLike( @@ -115,7 +119,7 @@ const PlaceBox = ({ place, mapId }: PlaceBoxProps) => { placeId: place.id, mapId, }) - revalidate(['places', mapId]) + revalidatePlaces(mapId) } catch (error) { setIsLikePlace(true) setIsRecentlyLike( @@ -136,9 +140,8 @@ const PlaceBox = ({ place, mapId }: PlaceBoxProps) => { mapId, }) - setIsAlreadyPick(false) + revalidatePlaces(mapId) setIsDeleteModalOpen(false) - window.location.reload() } catch (error) { if (error instanceof APIError || error instanceof Error) { notify.error(error.message) @@ -154,7 +157,6 @@ const PlaceBox = ({ place, mapId }: PlaceBoxProps) => { label: 'register', }) router.push(`/place/${place.kakaoId}/register`) - revalidate(['places', mapId]) } catch (error) { if (error instanceof APIError || error instanceof Error) { notify.error(error.message) diff --git a/src/app/place/[placeId]/register/register-box.tsx b/src/app/place/[placeId]/register/register-box.tsx index 61b95a8f..d53ec77d 100644 --- a/src/app/place/[placeId]/register/register-box.tsx +++ b/src/app/place/[placeId]/register/register-box.tsx @@ -16,6 +16,7 @@ import type { PlaceDetail } from '@/models/api/place' import { api } from '@/utils/api' import get조사 from '@/utils/조사' import useFetch from '@/hooks/use-fetch' +import { revalidatePlaces } from '@/app/actions' const toTagNames = (tags: TagItem[]): TagItem['name'][] => tags.map((tag) => tag.name) @@ -46,7 +47,8 @@ const RegisterBox = ({ tagNames: toTagNames(selectedTags), }) - revalidate(['map-list']) + revalidatePlaces(mapId) + notify.success('맛집 등록이 완료되었습니다.') router.safeBack({ defaultHref: `/place/${place.kakaoId}` }) } catch (error) { diff --git a/src/app/profile/[mapId]/[id]/place-item.tsx b/src/app/profile/[mapId]/[id]/place-item.tsx index 09adff37..008a4747 100644 --- a/src/app/profile/[mapId]/[id]/place-item.tsx +++ b/src/app/profile/[mapId]/[id]/place-item.tsx @@ -19,6 +19,7 @@ import { api } from '@/utils/api' import cn from '@/utils/cn' import { roundOnePoint } from '@/utils/number' import { getStarByScore } from '@/utils/score' +import { revalidatePlaces } from '@/app/actions' interface PlaceItemProps extends ClassName { selectedPlace: PlaceType @@ -29,7 +30,7 @@ interface PlaceItemProps extends ClassName { const PlaceItem = forwardRef( ({ selectedPlace, className, mapId, onRefreshOldPlace }, ref) => { const [isLikePlace, setIsLikePlace] = useState(false) - const { data: user, revalidate } = useFetch(api.users.me.get, { + const { data: user } = useFetch(api.users.me.get, { key: ['user'], }) @@ -56,7 +57,7 @@ const PlaceItem = forwardRef( placeId: place.id, mapId, }) - revalidate(['places', mapId]) + revalidatePlaces(mapId) } catch (error) { setIsLikePlace(false) if (error instanceof APIError || error instanceof Error) { @@ -78,7 +79,7 @@ const PlaceItem = forwardRef( placeId: place.id, mapId, }) - revalidate(['places', mapId]) + revalidatePlaces(mapId) } catch (error) { setIsLikePlace(true) if (error instanceof APIError || error instanceof Error) { diff --git a/src/app/search/[query]/result-place-map-popup.tsx b/src/app/search/[query]/result-place-map-popup.tsx index 518f20e6..8804fcb1 100644 --- a/src/app/search/[query]/result-place-map-popup.tsx +++ b/src/app/search/[query]/result-place-map-popup.tsx @@ -22,6 +22,7 @@ import { api } from '@/utils/api' import cn from '@/utils/cn' import { roundOnePoint } from '@/utils/number' import { getStarByScore } from '@/utils/score' +import { revalidatePlaces } from '@/app/actions' interface ResultPlaceMapPopupProps extends ClassName { mapId: MapInfo['id'] @@ -35,7 +36,7 @@ const ResultPlaceMapPopup = forwardRef( const [isLoading, setIsLoading] = useState(false) const [place, setPlace] = useState(null) - const { data: user, revalidate } = useFetch(api.users.me.get, { + const { data: user } = useFetch(api.users.me.get, { onLoadEnd: (userData) => { setIsLikePlace( !!place?.likedUser?.find((liked) => liked.id === userData.id), @@ -92,7 +93,7 @@ const ResultPlaceMapPopup = forwardRef( placeId: place.id, mapId, }) - revalidate(['places', mapId]) + revalidatePlaces(mapId) } catch (error) { setIsLikePlace(false) setIsRecentlyLike( @@ -112,7 +113,7 @@ const ResultPlaceMapPopup = forwardRef( placeId: place.id, mapId, }) - revalidate(['places', mapId]) + revalidatePlaces(mapId) } catch (error) { setIsLikePlace(true) setIsRecentlyLike( diff --git a/src/app/search/[query]/result-search-list.tsx b/src/app/search/[query]/result-search-list.tsx index 216f39b7..3db70ed9 100644 --- a/src/app/search/[query]/result-search-list.tsx +++ b/src/app/search/[query]/result-search-list.tsx @@ -15,6 +15,7 @@ import { api } from '@/utils/api' import cn from '@/utils/cn' import { formatDistance, getDistance } from '@/utils/location' import { allowUserPositionStorage } from '@/utils/storage' +import { revalidatePlaces } from '@/app/actions' interface ResultSearchListBoxProps extends ClassName { places: SearchPlace[] @@ -26,7 +27,7 @@ const ResultSearchListBox = ({ places, mapId, }: ResultSearchListBoxProps) => { - const { data: user, revalidate } = useFetch(api.users.me.get, { + const { data: user } = useFetch(api.users.me.get, { key: ['user'], }) const { userLocation } = useUserGeoLocation() @@ -87,7 +88,7 @@ const ResultSearchListBox = ({ if (!mapId) return optimisticUpdateLikeOrUnLike(placeId) await api.place.mapId.placeId.like.put({ placeId, mapId }) - revalidate(['places', mapId]) + revalidatePlaces(mapId) } catch (error) {} } @@ -96,7 +97,7 @@ const ResultSearchListBox = ({ if (!mapId) return optimisticUpdateLikeOrUnLike(placeId) await api.place.mapId.placeId.like.delete({ placeId, mapId }) - revalidate(['places', mapId]) + revalidatePlaces(mapId) } catch (error) {} } diff --git a/src/components/place/place-map-popup.tsx b/src/components/place/place-map-popup.tsx index c33f6949..315bbd76 100644 --- a/src/components/place/place-map-popup.tsx +++ b/src/components/place/place-map-popup.tsx @@ -20,6 +20,7 @@ import cn from '@/utils/cn' import { roundOnePoint } from '@/utils/number' import { getStarByScore } from '@/utils/score' import PlacePopupSkeleton from '@/components/place/place-popup-skeleton' +import { revalidatePlaces } from '@/app/actions' interface PlaceMapPopupProps extends ClassName { selectedPlace: PlaceType @@ -30,7 +31,7 @@ interface PlaceMapPopupProps extends ClassName { const PlaceMapPopup = forwardRef( ({ selectedPlace, className, mapId, onRefreshOldPlace }, ref) => { const [isLikePlace, setIsLikePlace] = useState(false) - const { data: user, revalidate } = useFetch(api.users.me.get, { + const { data: user } = useFetch(api.users.me.get, { key: ['user'], }) @@ -59,7 +60,7 @@ const PlaceMapPopup = forwardRef( placeId: place.id, mapId, }) - revalidate(['places', mapId]) + revalidatePlaces(mapId) } catch (error) { setIsLikePlace(false) if (error instanceof APIError || error instanceof Error) { @@ -81,7 +82,7 @@ const PlaceMapPopup = forwardRef( placeId: place.id, mapId, }) - revalidate(['places', mapId]) + revalidatePlaces(mapId) } catch (error) { setIsLikePlace(true) if (error instanceof APIError || error instanceof Error) { diff --git a/src/utils/api/index.ts b/src/utils/api/index.ts index 6bae68f6..e383395d 100644 --- a/src/utils/api/index.ts +++ b/src/utils/api/index.ts @@ -136,7 +136,10 @@ const search = { mapId, }: QueryParams & { mapId: MapInfo['id'] }): Promise< ResponseWithMessage - > => client.public.get(`/search/places?q=${q}&rect=${rect}&mapId=${mapId}`), + > => + client.public.get(`/search/places?q=${q}&rect=${rect}&mapId=${mapId}`, { + tags: ['places', mapId], + }), }, } From 5ca09baece411f1afb4ffea1d61cb9abb199d3c8 Mon Sep 17 00:00:00 2001 From: hee-suh Date: Fri, 4 Oct 2024 21:19:49 +0900 Subject: [PATCH 2/3] fix: prevent rendering of all places --- src/app/map/[mapId]/place-list-bottom-sheet.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/map/[mapId]/place-list-bottom-sheet.tsx b/src/app/map/[mapId]/place-list-bottom-sheet.tsx index eb4644f2..98816ffb 100644 --- a/src/app/map/[mapId]/place-list-bottom-sheet.tsx +++ b/src/app/map/[mapId]/place-list-bottom-sheet.tsx @@ -31,7 +31,7 @@ const PlaceListBottomSheet = forwardRef< { places, mapId, selectedFilter, onClickFilterButton, onRefreshOldPlace }, ref, ) => { - const [placeList, setPlaceList] = useState(places || []) + const [placeList, setPlaceList] = useState([]) const { data: slicedPlaceList, listRef } = useInfiniteScroll({ totalData: places || [], itemsPerPage: 10, From a1a8b8c6629686a1218e95b3cc5034e46525be7c Mon Sep 17 00:00:00 2001 From: hee-suh Date: Fri, 4 Oct 2024 21:22:31 +0900 Subject: [PATCH 3/3] fix: remove unused variables --- src/app/actions.ts | 2 +- src/app/place/[placeId]/register/register-box.tsx | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/app/actions.ts b/src/app/actions.ts index 3fd1f004..188ee322 100644 --- a/src/app/actions.ts +++ b/src/app/actions.ts @@ -1,7 +1,7 @@ 'use server' import { cookies } from 'next/headers' -import { revalidatePath, revalidateTag } from 'next/cache' +import { revalidateTag } from 'next/cache' const setCookie = async (name: string, value: string) => { cookies().set(name, value) diff --git a/src/app/place/[placeId]/register/register-box.tsx b/src/app/place/[placeId]/register/register-box.tsx index d53ec77d..5ea95768 100644 --- a/src/app/place/[placeId]/register/register-box.tsx +++ b/src/app/place/[placeId]/register/register-box.tsx @@ -15,7 +15,6 @@ import type { TagItem } from '@/models/api/maps' import type { PlaceDetail } from '@/models/api/place' import { api } from '@/utils/api' import get조사 from '@/utils/조사' -import useFetch from '@/hooks/use-fetch' import { revalidatePlaces } from '@/app/actions' const toTagNames = (tags: TagItem[]): TagItem['name'][] => @@ -30,7 +29,6 @@ const RegisterBox = ({ tags: TagItem[] mapId: string }) => { - const { revalidate } = useFetch() const router = useSafeRouter() const [selectedTags, setSelectedTags] = useState([]) const [isOpenBackModal, setIsOpenBackModal] = useState(false)