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";