-
Notifications
You must be signed in to change notification settings - Fork 1
feat: 댓글 likeCount 응답 포함 및 웹 좋아요 토글 연동 #284
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,10 +3,10 @@ import { IComment, IDeleteCommentRequest } from '@fienmee/types' | |
| import { useMutation, useQueryClient } from '@tanstack/react-query' | ||
| import { toast } from 'react-toastify' | ||
|
|
||
| import { deleteEventCommentById } from '@/api/event' | ||
| import { deleteEventCommentById, toggleEventCommentLike } from '@/api/event' | ||
| import CommentOption from '@/components/comment/commentOption' | ||
| import CommentUpdateField from '@/components/comment/commentUpdateField' | ||
| import { UnlikeIcon } from '@/components/icon' | ||
| import { LikeIcon, UnlikeIcon } from '@/components/icon' | ||
| import LoadingOverlay from '@/components/comment/commentLoadingOverlay' | ||
|
|
||
| interface Props { | ||
|
|
@@ -36,6 +36,21 @@ export function EventComment({ comment }: Props) { | |
| }) | ||
| } | ||
|
|
||
| const likeMutation = useMutation({ | ||
| mutationFn: ({ eventId, commentId }: { eventId: string; commentId: string }) => toggleEventCommentLike(eventId, commentId), | ||
| onSuccess: async () => { | ||
| await queryClient.invalidateQueries({ queryKey: ['comments', comment.eventId] }) | ||
| }, | ||
| onError: () => { | ||
| toast.error(<span>좋아요 처리에 실패했습니다.</span>) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 좋아요가 제대로 반영되지 않았어요. 다시 시도해주세요. 이런것 처럼 문구를 바꾸는게 좋을 것 같아요.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 변경 했습니다! |
||
| }, | ||
| }) | ||
|
Comment on lines
+39
to
+47
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 좋아요 기능이 낙관적 업데이트를 사용하면, 서버 응답을 기다리지 않고 UI를 먼저 변경하여 사용자에게 즉각적인 피드백을 줄 수 있습니다. 만약 서버 요청이 실패하면 원래 상태로 되돌립니다.
|
||
|
|
||
| const handleToggleLike = () => { | ||
| if (likeMutation.isPending) return | ||
| likeMutation.mutate({ eventId: comment.eventId, commentId: comment._id }) | ||
| } | ||
|
|
||
| return ( | ||
| <div className="flex flex-col gap-6 py-2 relative"> | ||
| {deleteMutation.isPending && <LoadingOverlay />} | ||
|
|
@@ -49,7 +64,16 @@ export function EventComment({ comment }: Props) { | |
| )} | ||
| </div> | ||
| <div className="flex flex-row justify-center items-center gap-2"> | ||
| <UnlikeIcon width="1.5rem" height="1.25rem" /> | ||
| <button | ||
| aria-label="toggle comment like" | ||
| onClick={handleToggleLike} | ||
| disabled={likeMutation.isPending} | ||
| className="disabled:opacity-50" | ||
| type="button" | ||
| > | ||
| {comment.isLiked ? <LikeIcon width="1.5rem" height="1.25rem" /> : <UnlikeIcon width="1.5rem" height="1.25rem" />} | ||
| </button> | ||
| <span className="text-sm">{comment.likeCount}</span> | ||
| {comment.isAuthor && ( | ||
| <CommentOption onEdit={() => setIsEdit(true)} onDelete={handleDelete} isDeleteDisabled={deleteMutation.isPending} /> | ||
| )} | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
새로운
likeCount필드가 응답에 잘 추가되었습니다. 다만, 이 로직은apps/server/src/models/comments.ts의toJSON메서드에 정의된 로직과 중복됩니다. 작성자님께서도 PR 설명에 언급해주셨듯이, 현재는toObject()를 사용하기 때문에 모델의toJSON에 정의된likeCount가 포함되지 않는 문제가 있습니다.장기적인 유지보수성을 위해, 모델 레이어에서 데이터 가공을 처리하는 것이 좋습니다. 한 가지 방법은 Mongoose의 가상(virtual) 프로퍼티를 사용하는 것입니다. 모델 스키마에
likeCount를 가상 프로퍼티로 정의하고toObject: { virtuals: true }옵션을 활성화하면, 컨트롤러에서 별도의 로직 없이comment.toObject()를 통해 일관되게likeCount값을 얻을 수 있습니다. 이는 코드 중복을 줄이고 역할을 명확히 분리하는 데 도움이 될 것입니다. 추후 리팩토링 시 고려해보시면 좋겠습니다.