diff --git a/src/app/post/[id]/components/PostMemo/PostMemo.tsx b/src/app/post/[id]/components/PostMemo/PostMemo.tsx index a7a86699..dfb558a9 100644 --- a/src/app/post/[id]/components/PostMemo/PostMemo.tsx +++ b/src/app/post/[id]/components/PostMemo/PostMemo.tsx @@ -2,18 +2,14 @@ import * as S from "./PostMemo.styles"; import Avatar from "@/components/Avatar/Avatar"; import { Heart, Location, ViewIcon } from "@/components/icons"; -import { useUI } from "@/components/uiContext/UiContext"; -import { fetchPostLikedToggle } from "@/lib/api/Post/client"; import { getUserInfo } from "@/lib/api/User/client"; -import { POST_KEY, USER_KEY } from "@/lib/api/queryKeys"; -import useAuthStore from "@/lib/stores/useAuthStore"; +import { USER_KEY } from "@/lib/api/queryKeys"; import { calculateWalkingCalories, convertMeter, convertSeconds } from "@/lib/utils"; -import checkErrorCode from "@/lib/utils/checkErrorCode"; import { UserInfoType } from "@/types/Response"; import { PostDetailResponse } from "@/types/Response/Post"; -import { useMutation, useQuery } from "@tanstack/react-query"; +import { useQuery } from "@tanstack/react-query"; -import { useRouter } from "next/navigation"; +import { useLikeMutation } from "./hooks"; interface PostMemoProps { userInfo: UserInfoType; @@ -37,46 +33,18 @@ const PostMemo = ({ userInfo, postData }: PostMemoProps) => { } = postData; const { isUserInfoCheck, calories } = calculateWalkingCalories({ userInfo, distance }); - const { setModalView, openModal } = useUI(); - const router = useRouter(); - const { isLogIn } = useAuthStore(); const { data: authorData } = useQuery({ queryKey: [USER_KEY.USER_INFO, authorId], queryFn: () => getUserInfo(String(authorId)), }); - const likeMutation = useMutation({ - mutationKey: [POST_KEY.LIKED_STATUS], - mutationFn: fetchPostLikedToggle, - onSuccess: () => { - router.refresh(); - }, - onError: ({ message }) => { - setModalView("ANIMATION_ALERT_VIEW"); - openModal({ - message: checkErrorCode({ - errorCode: message, - defaultMessage: "해당 요청에 문제가 발생하였습니다.
잠시 후 다시 시도해주세요!", - }), - }); - }, - }); + const { isLike, likes, handleClickLike } = useLikeMutation({ id, isLiked, likeCount }); if (!authorData) { return; } - const handleClickLike = () => { - if (!isLogIn) { - setModalView("ACCESS_LOGIN_VIEW"); - openModal(); - return; - } - - likeMutation.mutate({ postId: String(id), data: { isLike: !isLiked } }); - }; - return ( <> {title} @@ -112,10 +80,10 @@ const PostMemo = ({ userInfo, postData }: PostMemoProps) => { - {likeCount} + {likes} diff --git a/src/app/post/[id]/components/PostMemo/hooks/index.ts b/src/app/post/[id]/components/PostMemo/hooks/index.ts new file mode 100644 index 00000000..b0b6c26f --- /dev/null +++ b/src/app/post/[id]/components/PostMemo/hooks/index.ts @@ -0,0 +1 @@ +export { default as useLikeMutation } from "./useLikeMutation/useLikeMutation"; diff --git a/src/app/post/[id]/components/PostMemo/hooks/useLikeMutation/useLikeMutation.ts b/src/app/post/[id]/components/PostMemo/hooks/useLikeMutation/useLikeMutation.ts new file mode 100644 index 00000000..67c98d47 --- /dev/null +++ b/src/app/post/[id]/components/PostMemo/hooks/useLikeMutation/useLikeMutation.ts @@ -0,0 +1,80 @@ +import { useCallback, useState } from "react"; + +import { useUI } from "@/components/uiContext/UiContext"; +import { fetchPostLikedToggle } from "@/lib/api/Post/client"; +import { POST_KEY } from "@/lib/api/queryKeys"; +import useAuthStore from "@/lib/stores/useAuthStore"; +import checkErrorCode from "@/lib/utils/checkErrorCode"; +import { LikesResponse } from "@/types/Response"; +import { useMutation } from "@tanstack/react-query"; + +import { debounce } from "lodash"; +import { useRouter } from "next/navigation"; + +interface UseLikeMutationProps { + id: number; + isLiked: boolean; + likeCount: number; +} + +const useLikeMutation = ({ id, isLiked, likeCount }: UseLikeMutationProps) => { + const router = useRouter(); + const [isLike, setIsLike] = useState(isLiked); + const [likes, setLikes] = useState(likeCount); + const [isCurrentLiked, setIsCurrentLiked] = useState(isLiked); + + const { setModalView, openModal } = useUI(); + const { isLogIn } = useAuthStore(); + + const likeMutation = useMutation({ + mutationKey: [POST_KEY.LIKED_STATUS], + mutationFn: fetchPostLikedToggle, + onSuccess: ({ isLike }: LikesResponse) => { + setIsCurrentLiked(isLike); + router.refresh(); + }, + onError: ({ message }) => { + setModalView("ANIMATION_ALERT_VIEW"); + openModal({ + message: checkErrorCode({ + errorCode: message, + defaultMessage: "해당 요청에 문제가 발생하였습니다.
잠시 후 다시 시도해주세요!", + }), + }); + }, + }); + + const handleLikeMutation = useCallback( + debounce((postId, isLike) => { + if (isCurrentLiked === isLike) { + return; + } + + likeMutation.mutate({ postId: String(postId), data: { isLike: isLike } }); + }, 1000), + [isCurrentLiked], + ); + + const handleClickLike = () => { + if (!isLogIn) { + setModalView("ACCESS_LOGIN_VIEW"); + openModal(); + return; + } + + setLikes((likes) => (isLike ? likes - 1 : likes + 1)); + setIsLike((prevIsLike) => { + const newIsLike = !prevIsLike; + handleLikeMutation(id, newIsLike); + return newIsLike; + }); + }; + + return { + isLike, + likes, + handleClickLike, + }; +}; + +export default useLikeMutation; diff --git a/src/lib/api/Post/client.ts b/src/lib/api/Post/client.ts index 4a8f32e1..d27cba44 100644 --- a/src/lib/api/Post/client.ts +++ b/src/lib/api/Post/client.ts @@ -1,4 +1,5 @@ import { PostCreateRequest, PostListRequest } from "@/types/Request"; +import { LikesResponse } from "@/types/Response"; import { PostDetailResponse, PostListResponse } from "@/types/Response/Post"; import { DELETE, GET, POST, PUT } from "../clientRootAPI"; @@ -41,7 +42,10 @@ interface fetchPostLikeToggleProps { data: { isLike: boolean }; } -export const fetchPostLikedToggle = async ({ postId, data }: fetchPostLikeToggleProps) => { +export const fetchPostLikedToggle = async ({ + postId, + data, +}: fetchPostLikeToggleProps): Promise => { return await PUT({ endPoint: END_POINT.POST.LIKED_STATUS(postId), data, diff --git a/src/types/Response/Like.ts b/src/types/Response/Like.ts new file mode 100644 index 00000000..efd05638 --- /dev/null +++ b/src/types/Response/Like.ts @@ -0,0 +1,3 @@ +export interface LikesResponse { + isLike: boolean; +} diff --git a/src/types/Response/index.ts b/src/types/Response/index.ts index 8b4c4030..869ecb4d 100644 --- a/src/types/Response/index.ts +++ b/src/types/Response/index.ts @@ -1,3 +1,4 @@ export * from "./User"; export * from "./Masil"; export * from "./mate"; +export * from "./Like";