-
Notifications
You must be signed in to change notification settings - Fork 0
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
Feat/#37: 게시글 상세 댓글, 좋아요, 스크랩 기능 구현 #53
Conversation
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.
수고하셨습니다. 로직이 많아서 눈에 띄는 것 위주로 짧게 리뷰했습니다!
const usePostCommentMutation = ({ feedId, onSuccess }: Props) => { | ||
const queryClient = useQueryClient(); | ||
const { mutate: postComment, ...rest } = useMutation({ | ||
mutationFn: _postComment, | ||
onSuccess: () => { | ||
queryClient.invalidateQueries({ queryKey: ['comments', feedId] }); | ||
queryClient.invalidateQueries({ queryKey: ['feedDetail', feedId] }); | ||
if (onSuccess) onSuccess(); | ||
}, | ||
onError: (error: AxiosError<{ message: string }>) => { | ||
alert(error.response?.data.message ?? '댓글 작성에 실패했습니다.'); | ||
}, | ||
}); | ||
|
||
return { postComment, ...rest }; | ||
}; | ||
|
||
export default usePostCommentMutation; |
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.
onSuccess를 prop으로 또 선언을 해줄필요가 없습니다.
...rest로 넘겨주었기 때문에, mutation 사용처에서 option으로 onSuccess 콜백을 선언해주면, 알아서 처리가 되더라구요.
사실 저도 처음 react-query쓸 때 같은 실수를 했습니다😄
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.
아하 사용처에서 option으로 onSuccess 콜백을 선언해준다는게 어떻게 사용되는 것인지 알 수 있을까여? 처음 안 사실이군요
|
||
const _editComment = (commentId: string, payload: CommentPayload) => http.patch(`/comments/${commentId}`, payload); | ||
|
||
const usePatchCommentMutation = ({ feedId, commentId, onSuccess }: Props) => { |
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.
저는 mutation은 따로 뒤에 붙이지 않는 편입니다.
Patch, Post, Put 처럼 앞에서 붙여져 있기 때문인데요, 이건 취향차이라고 생각합니다.
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.
오호 저도 Mutation postfix를 계속 붙이다보니 네이밍이 너무 길어지더군요. Delete, Patch, Put 키워드를 삭제하자니 기능이 제대로 명시가 안되는 것 같고..
Mutation postfix 일괄 삭제할께여~
|
||
return ( | ||
<> | ||
<CommentFocusProvider> |
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.
이게 어떤역할을 하나요?
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.
요 부분이 아래 세 가지 기능을 컨트롤 합니다.
- 댓글 입력창 상태 관리 및 포커싱, 포커싱 아웃 로직 관리 (댓글 맨 위 상단의 댓글 입력창)
- 대댓글 입력창 포커싱, 포커싱 아웃 로직 관리 (각 댓글 마다 생성 가능한 대댓글 입력창)
- 댓글 및 대댓글 수정 입력창 포커싱, 포커싱 아웃 로직 관리 (각 댓글, 대댓글 수정 시 보이는 입력창)
2번과 3번은 동일하게 생겼지만 1번이 조금 특이합니다. 1번의 경우에는 게시글 상세 통 틀어서 하나의 입력창이고 입력 값에 따라서 댓글창을 확장할지 축소할지 등의 로직이 추가됩니다. 그래서 컨텍스트 내부에 1번 입력창의 상태가 있고 2번, 3번 입력창은 각 컴포넌트의 로컬 상태로 관리됩니다. (각 댓글, 대댓글 마다 생성해야하므로)
위 기능을 관리하는 컨텍스트가 되겠습니다.
<Box padding="20px 22px"> | ||
<WriteComment feedId={feedId} myImageUrl={myImageUrl} myNickname={myNickname} /> | ||
{comments.map((comment, idx) => ( | ||
<Fragment key={comment.content}> |
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.
key를 comment.parentCommentId
로 하는건 어떤가요?
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.
이 부분 역시 수정해두겠습니다.
type CommentFocusContextType = { | ||
isFocusComment: boolean; | ||
openCommentTextarea: () => void; | ||
focusRecommentTextarea: () => void; | ||
closeCommentTextarea: () => void; | ||
initRecommentTextareaRef: () => void; | ||
focusEditCommentTextarea: () => void; | ||
initEditCommentTextarea: () => void; | ||
commentTextareaRef: MutableRefObject<HTMLTextAreaElement | null>; | ||
recommentTextareaRef: MutableRefObject<HTMLTextAreaElement | null>; | ||
editCommentTextareaRef: MutableRefObject<HTMLTextAreaElement | null>; | ||
}; |
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.
와우.... 스크롤하는 부분 로직 같은데 복잡하네요ㅋㅋㅋㅋ
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.
네 이 부분이 좀 많이 어지러운데 그렇다고 컨텍스트를 여러개로 나눠서 컨텍스트 세 개를 감싸자니 좀 애매하고..
그래서 로직은 한 곳으로 몰아두고 커스텀 훅을 활용해서 가져오는 값을 제한하는 방식으로 진행했습니다.
const { mutate: deleteScrap, ...rest } = useMutation({ | ||
mutationFn: _deleteScrap, | ||
onSuccess: () => { | ||
queryClient.invalidateQueries({ queryKey: ['feedDetail', id] }); |
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.
queryKey 선언 방식이 약간 어색하게 느껴집니다.
['feeds', 'detail', id] 는 어떤가요?
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.
오우 좋습니다. 반영해둘께요.
const _postComment = (payload: CommentPayload) => http.post('/comments', payload); | ||
|
||
const usePostCommentMutation = ({ feedId, onSuccess }: Props) => { | ||
const queryClient = useQueryClient(); | ||
const { mutate: postComment, ...rest } = useMutation({ | ||
mutationFn: _postComment, | ||
onSuccess: () => { | ||
queryClient.invalidateQueries({ queryKey: ['comments', feedId] }); | ||
queryClient.invalidateQueries({ queryKey: ['feedDetail', feedId] }); | ||
if (onSuccess) onSuccess(); | ||
}, | ||
onError: (error: AxiosError<{ message: string }>) => { | ||
alert(error.response?.data.message ?? '댓글 작성에 실패했습니다.'); | ||
}, | ||
}); | ||
|
||
return { postComment, ...rest }; | ||
}; | ||
|
||
export default usePostCommentMutation; |
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.
queryKey ['comments', feedId] 부분이 잘 이해가 되지 않습니다. 해석 가능할까요?
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.
댓글 무한스크롤 조회 쿼리키 입니다. 각 게시글 id 값으로 댓글을 조회하고 있는데, 댓글을 작성하거나 삭제한 후 해당 쿼리 키를 무효화하여 댓글 리스트를 최신화 하고 있습니다.
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.
그렇군요. 더 나은 쿼리키 선언 방법이 있는지 고민해보면 좋을 것 같아요.
저도 당장은 모르겠는데, comments 뒤에 feed의 id가 나오니까 조금 어색한 느낌이 들었네요
|
||
{commentChildResponses.map((recomment, idx) => ( | ||
<Recomment key={idx} recomment={recomment} /> | ||
<Recomment key={idx} feedId={feedId} recomment={recomment} myImageUrl={myImageUrl} myNickname={myNickname} /> |
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.
이 부분도 key로 recomment.childCommentId
는 어떨까요
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.
오우 좋습니다. id 값이 서버에 반영되기 전에 로직을 미쳐 수정하지못했군요. 수정해두겠습니다.
추가로 현재 서버에서 댓글 및 대댓글 좋아요, 좋아요 해제 기능이 도입되어서 이 부분과 리팩토링을 같이 반영해두도록 하겠습니다. |
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.
수고하셨어요
📄 Summary
close #37
디자인 시스템 반영 사항은 다음과 같습니다. 0.4.2 PR, 0.4.3 PR 두 PR 모두 기존 컴포넌트 UI 오류나 기능을 추가한 것으로 기존의 사용 방법이 변경되어 오류를 발생시키거나 하지는 않습니다.
🙋🏻 More
추가로 중복 코드가 좀 있습니다. 그리고 댓글 창 확대 시 포커싱 하는 기능이 WriteComment, WriteRecomment 내부에 있으며 상태와 ref는 CommentFocusContext에서 가져옵니다. 이 부분이 살짝 복잡할 수 있습니다.
서버와 연동 작업 완료 후 ready for review 상태로 변경해두겠습니다.
댓글 및 대댓글 동작 (포커싱, 확대 등)
PC 환경
Mobile 가상키보드 환경