목차 돌아가기:
binaryjourney.tistory.com/pages/ReactCRUD-create-board-tutorial
앞서 말했듯이 댓글 삭제 기능을 구현해보겠다
일단 ArticlePage에 빈 이벤트함수 onDeleteComment 를 만들어서 ArtDetail 에 deleteComment라는 프로퍼티에 넘겨준다.
// ArticlePage
const onDeleteComment = (commentId) => {};
return (
<div style={{ width: "80%", margin: "3rem auto" }}>
<div>
<ArticleDetail
id={id}
title={title}
content={content}
views={views}
date={date}
handleDeleteClick={onDeleteClick}
handleComment={
<Comment
comment={CommentValue}
handleCommentChange={onCommentChange}
handleCommentSubmit={onCommentSubmit}
/>
}
loadComments={comments}
deleteComment={onDeleteComment}
/>
</div>
</div>
);
ArticleDetail 에서는 날짜시간 바로 오른쪽에 삭제버튼으로 [x]을 만들고 앞서 만든 이벤트함수를 props.deleteComment로 받아 onClick 으로 넣어준다.
// ArticleDetail
<div>
{props.loadComments.map((comment) => (
<div
style={{
width: "100%",
backgroundColor: "lightsteelblue",
border: "1px dotted black",
}}
>
<span key={comment.id}>
<span>{comment.content}</span>
<span style={{ float: "right" }}>
{new Date(comment.date).toLocaleString()}
<span
style={{ cursor: "pointer" }}
onClick={props.deleteComment}
>
[X]
</span>
</span>
</span>
</div>
))}
[x] 위로 마우스가 가면 모양이 바뀌도록 스타일도 넣어줬다.
원래 button 태그로 하려고 했는데 css 손을 댈 수가 없어서 결국 span 태그로 만들어줬다.
화면에선 이렇게 보인다.
16편 글을 모두 본 사람은 이제 만드는 순서가 익숙해져 있을 것이다
1. slice에서 액션만들고
// commentSlice
deleteComment: (state, { payload: id }) => {
console.log("댓글 삭제 액션 호출 -- deleteComments"); // saga 에서 감시용
},
2. saga에서 액션과 같이 처리할 함수를 만들고
// commentSaga
export function* deleteCommentAsync(action) {
const commentId = action.payload;
yield Axios.delete(`http://localhost:4000/comment/${commentId}`);
history.go(0);
}
3. rootSaga에 액션타입과 saga에서 만든 함수를 적고 (엄청나게 뚱뚱해진 rootSaga ㄷㄷㄷㄷㄷ)
// rootSaga
import { take, takeEvery, takeLatest } from "redux-saga/effects";
import { articleActions } from "../slice/articleSlice";
import { boardActions } from "../slice/boardSlice";
import { commentActions } from "../slice/commentSlice";
import {
registerArticleAsync,
getArticleAsync,
fetchArticleAsync,
updateArticleAsync,
deleteArticleAsync,
} from "./articleSaga";
import { getBoardAsync } from "./boardSaga";
import {
registerCommentAsync,
getCommentsAsync,
deleteCommentAsync, // 추가
} from "./commentSaga";
const {
registerArticle,
getArticle,
fetchArticle,
updateArticle,
deleteArticle,
} = articleActions;
const { getBoard } = boardActions;
const { registerComment, getComments, deleteComment } = commentActions;
export default function* rootWatcher() {
yield takeLatest(registerArticle.type, registerArticleAsync);
yield takeEvery(getArticle.type, getArticleAsync);
yield takeEvery(getBoard.type, getBoardAsync);
yield takeEvery(fetchArticle.type, fetchArticleAsync);
yield takeLatest(updateArticle.type, updateArticleAsync);
yield takeLatest(deleteArticle.type, deleteArticleAsync);
yield takeLatest(registerComment.type, registerCommentAsync);
yield takeEvery(getComments.type, getCommentsAsync);
yield takeLatest(deleteComment.type, deleteCommentAsync); // 추가
}
4. 컨테이너 컴포넌트에 만들어놓은 빈 이벤트 함수에 해당 액션함수를 import 하여 dispatch 해주는 것
- 근데 프레젠테이셔널 컴포넌트에도 수정이 필요하다
// ArticlePage
const onDeleteComment = (commentId) => {
dispatch(commentActions.deleteComment(commentId));
};
// ArticleDetail
<div>
{props.loadComments.length > 0 && {/* 수정 부분 */}
props.loadComments.map((comment) => (
<div
style={{
width: "100%",
backgroundColor: "lightsteelblue",
border: "1px dotted black",
}}
>
<span key={comment.id}>
<span>{comment.content}</span>
<span style={{ float: "right" }}>
{new Date(comment.date).toLocaleString()}
<span
style={{ cursor: "pointer" }}
onClick={() => props.deleteComment(comment.id)} {/* 수정부분 */}
>
[X]
</span>
</span>
</span>
</div>
))}
</div>
(조건문도 넣어줬다)
작성한 파일을 저장하고 이제 [x] 를 눌러보자
json server에 delete가 보이는가?
아래 이미지와 비교해보자
11:30:56 에 쓴 댓글이 삭제되었다.
json server 데이터를 봐도 삭제가 성공한 것을 알 수 있다
분량이 길어서 목록에 댓글 개수 나타내는 것은 다음 편에서 다루겠다
목차 돌아가기: binaryjourney.tistory.com/pages/ReactCRUD-create-board-tutorial