Skip to content

Commit

Permalink
[ Refactor ] 산책로 포스트 페이지 (좋아요 기능 개선) (#348)
Browse files Browse the repository at this point in the history
* 📝docs: LikeResponse 타입 추가
- fetchPostLikedToggle 함수에 대한 반환 타입 지정

* ♻️refactor: Post 페이지 좋아요 기능 분리 및 성능 개선
- debounce 함수 적용으로 최종 상태에 따른 API 호출 (마지막 한 번만 호출함)
- 만약 현재 좋아요 상태와 동일한 경우 API 호출되지 않도록 조건문 추가
- 낙관적 업데이트 되도록 수정

* 🚜change: 주석 제거
  • Loading branch information
SeungHyune authored Oct 8, 2024
1 parent ed7e7ef commit 60ba1eb
Show file tree
Hide file tree
Showing 6 changed files with 96 additions and 39 deletions.
44 changes: 6 additions & 38 deletions src/app/post/[id]/components/PostMemo/PostMemo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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: "해당 요청에 문제가 발생하였습니다.<br>잠시 후 다시 시도해주세요!",
}),
});
},
});
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 (
<>
<S.PostMemoTitle>{title}</S.PostMemoTitle>
Expand Down Expand Up @@ -112,10 +80,10 @@ const PostMemo = ({ userInfo, postData }: PostMemoProps) => {
<S.PostMemoBottomInfo>
<S.PostMemoLike
onClick={handleClickLike}
$isLiked={isLiked}
$isLiked={isLike}
>
<Heart />
{likeCount}
{likes}
</S.PostMemoLike>
<S.PostMemoViewCount>
<ViewIcon />
Expand Down
1 change: 1 addition & 0 deletions src/app/post/[id]/components/PostMemo/hooks/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default as useLikeMutation } from "./useLikeMutation/useLikeMutation";
Original file line number Diff line number Diff line change
@@ -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: "해당 요청에 문제가 발생하였습니다.<br>잠시 후 다시 시도해주세요!",
}),
});
},
});

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;
6 changes: 5 additions & 1 deletion src/lib/api/Post/client.ts
Original file line number Diff line number Diff line change
@@ -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";
Expand Down Expand Up @@ -41,7 +42,10 @@ interface fetchPostLikeToggleProps {
data: { isLike: boolean };
}

export const fetchPostLikedToggle = async ({ postId, data }: fetchPostLikeToggleProps) => {
export const fetchPostLikedToggle = async ({
postId,
data,
}: fetchPostLikeToggleProps): Promise<LikesResponse> => {
return await PUT({
endPoint: END_POINT.POST.LIKED_STATUS(postId),
data,
Expand Down
3 changes: 3 additions & 0 deletions src/types/Response/Like.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export interface LikesResponse {
isLike: boolean;
}
1 change: 1 addition & 0 deletions src/types/Response/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from "./User";
export * from "./Masil";
export * from "./mate";
export * from "./Like";

0 comments on commit 60ba1eb

Please sign in to comment.