-
카테고리
-
세부 분야
풀스택
-
해결 여부
미해결
강좌 끝나고 댓글 수정 기능 만들어 보고 있습니다
23.09.26 15:12 작성 조회수 193
0
{commentFormOpened && (
<div>
{commentEditMode
?
<CommentContent post={post} commentEditMode={commentEditMode} onClickUpdateComment={onClickUpdateComment} onCancelUpdateComment={onCancelUpdateComment} />
: (
<>
<CommentForm post={post} />
<CommentContent post={post} commentEditMode={commentEditMode} onClickUpdateComment={onClickUpdateComment} onCancelUpdateComment={onCancelUpdateComment} />
</>
)
}
</div>
)}
//PostCard.js
import React, { useCallback, useEffect, useState } from 'react';
import { Avatar, Comment, List, Input, Button, Popover } from 'antd';
import { useDispatch, useSelector } from 'react-redux';
import Link from 'next/link';
import PropTypes from 'prop-types';
import { EllipsisOutlined } from '@ant-design/icons';
import { UPDATE_COMMENT_REQUEST } from '../reducers/post';
const {TextArea} = Input;
const CommentContent = ({ post, onCancelUpdateComment, commentEditMode, onClickUpdateComment }) => {
const dispatch = useDispatch();
const id = useSelector((state) => state.user?.me.id);
const { updateCommentLoading, updateCommentDone } = useSelector((state) => state.post);
const [editText, setEditText] = useState(post.Comments.content);
useEffect(() => {
if (updateCommentDone) {
onCancelUpdateComment();
}
}, [updateCommentDone]);
const onChangeCommentText = useCallback((e) => {
setEditText(e.target.value);
}, []);
const onChangeComment = useCallback(() => {
dispatch({
type: UPDATE_COMMENT_REQUEST,
data: {
PostId: post.id,
CommentId: post.Comments.id,
UserId: id,
content: editText,
},
});
}, [post, id, editText, post.Comments.id]);
return (
<div>
{commentEditMode
? (
<>
<TextArea value={editText} onChange={onChangeCommentText} />
<Button.Group>
<Button loading={updateCommentLoading} onClick={onChangeComment}>수정</Button>
<Button type="danger" onClick={onCancelUpdateComment}>수정 취소</Button>
</Button.Group>
</>
)
:
<List
header={`${post.Comments.length}개의 댓글`}
itemLayout="horizontal"
dataSource={post.Comments}
renderItem={(item) => (
<li>
<Comment
actions={[<Popover
key="more"
content={
<Button.Group>
{id && item.User.id === id ? (
<>
<Button onClick={onClickUpdateComment}>수정</Button>
<Button type="danger">
삭제
</Button>
</>
) : (
<Button>신고</Button>
)}
</Button.Group>
}
>
<EllipsisOutlined />
</Popover>,]}
author={item.User.nickname}
avatar={
<Link href={`/user/${item.User.id}`}>
<a><Avatar>{item.User.nickname[0]}</Avatar></a>
</Link>
}
content={item.content}
/>
</li>
)}
/>
}
</div>
)
}
CommentContent.propTypes = {
post: PropTypes.shape({
id: PropTypes.number.isRequired,
Comments: PropTypes.arrayOf(PropTypes.shape({
id: PropTypes.number.isRequired,
content: PropTypes.string.isRequired,
}))
}),
onCancelUpdateComment: PropTypes.func.isRequired,
onClickUpdateComment: PropTypes.func.isRequired,
commentEditMode: PropTypes.bool
};
CommentContent.defaultsProps = {
commentEditMode: false,
}
export default CommentContent;
//CommentContent.js
case UPDATE_COMMENT_REQUEST:
draft.updateCommentLoading = true;
draft.updateCommentDone = false;
draft.updateCommentError = null;
break;
case UPDATE_COMMENT_SUCCESS:
draft.updateCommentLoading = false;
draft.updateCommentDone = true;
const post = draft.mainPosts.find((v) => v.id === action.data.PostId);
post.Comments = post.Comments.find((v) => v.id === action.data.CommentId);
post.Comments = post.Comments.find((v) => v.id === action.data.UserId);
post.Comments.content = action.data.content;
break;
case UPDATE_COMMENT_FAILURE:
draft.updateCommentLoading = false;
draft.updateCommentError = action.error;
break;
//reducers/post.js
function updateCommentAPI(data) {
return axios.patch(`/post/${data.PostId}/comment`, data);
}
function* updateComment(action) {
try {
const result = yield call(updateCommentAPI, action.data);
yield put({
type: UPDATE_COMMENT_SUCCESS,
data: result.data,
});
} catch (err) {
console.error(err);
yield put({
type: UPDATE_COMMENT_FAILURE,
error: err.response.data,
});
}
}
// sagas/post.js
router.patch('/:postId/comment', isLoggedIn, async (req, res, next) => { // PATCH post/2/comment
try {
await Comment.update({
content: req.body.content,
}, {
where: {
PostId: req.params.postId,
UserId: req.user.id,
},
});
res.status(200).json({
PostId: parseInt(req.params.postId, 10),
UserId: req.user.id,
content: req.body.content,
});
} catch (error) {
console.error(error);
next(error);
}
});
//routes/post.js
이렇게 PostId, UserId, content가 보내지고, 실패가 뜨면서 새로고침을 하면 해당 글에 달았던 댓글들이 모두 다 "zzz"로 변경되어 있습니다. 그래서 CommentId를 보내줘야 될 거 같은데 여기서 막혀서 감이 도무지 잡히질 않습니다.
답변을 작성해보세요.
0
조현영
지식공유자2023.09.26
지금 댓글창 자체를 댓글수정창으로 재사용하고 계신 것 같은데 commentEditMode를 true로 바꿀 때 commentId도 같이 redux에 저장해두세요.
아니면 댓글 수정창을 따로 Comment component에 만드시면 됩니다. Comment 컴포넌트에서는 comment.id에 접근 가능하게 되니까요.
서버에서는 where: { id: commentId } 이런 식으로 특정 comment만 타겟해서 수정해야 합니다.
리듀서 부분도 다음과 같이 하나만 찾아서 수정해야 합니다.
const comment = post.Comments.find((v) => v.id === action.data.CommentId);
comment.content = action.data.content;
답변 1