티스토리 뷰
1. SingleComment.js 생성
아래의 이미지처럼 해당하는 위치에 SingleComment.js파일을 생성한다.
2. Single Comment를 위한 Template 생성
만든 파일에 아래와 같은 템플릿을 작성한다.
// client > src > components > views > VideoDetailPage > Sections > SingleComment.js
import React from "react";
import { Comment, Avatar, Button, Input } from "antd";
const { TextArea } = Input;
function SingleComment() {
return (
<div>
<Comment action author avatar={<Avatar src alt />} content />
<form style={{ display: "flex" }} onSubmit>
<textarea
style={{ width: "100%", borderRadius: "5px" }}
placeholder="코멘트를 작성해주세요."
onChange
value
/>
<br />
<button style={{ width: "20%", height: "52px" }} onClick>
Submit
</button>
</form>
</div>
);
}
export default SingleComment;
이렇게 만든 경우 아래와 같은 하단에 이미지로 바뀔 것이다.
3. Open Reply func와 handleChange func 만들기
3-1. Open Reply func
두 개의 form을 하나는 reply to를 클릭하였을 때만 보여주는 함수를 만들려 한다.
// client > src > components > views > VideoDetailPage > Sections > SingleComments.js
import React, { useState } from "react";
import { Comment, Avatar, Button, Input } from "antd";
const { TextArea } = Input;
function SingleComment() {
const [OpenReply, setOpenReply] = useState(false);
const onClickReplyOpen = () => {
setOpenReply(!OpenReply);
};
const actions = [
<span onClick={onClickReplyOpen} key="comment-basic-reply-to">
Reply to
</span>,
];
return (
<div>
<Comment actions={actions} author avatar={<Avatar src alt />} />
{OpenReply && (
<form style={{ display: "flex" }}>
<textarea
style={{ width: "100%", borderRadius: "5px" }}
placeholder="코멘트를 작성해주세요."
/>
<br />
<button style={{ width: "20%", height: "52px" }}>Submit</button>
</form>
)}
</div>
);
}
export default SingleComment;
useState를 사용하여 코멘트를 사라지고 보이게 할 수 있게 해 준다. OpenReply를 이용하여 토글 기능을 활용(!OpenReplay : 토글로 On/Off 기능을 사용)하여 On이 되었을 때, form값을 실행하도록 코딩을 하였다.
3-2. handleChange func
다음으로는 코멘트를 쓰고 value값을 넣는 함수를 만들어보도록 하겠다.
// client > src > components > views > VideoDetailPage > Sections > SingleComments.js
import React, { useState } from "react";
import { Comment, Avatar, Button, Input } from "antd";
const { TextArea } = Input;
function SingleComment() {
// 중략
const [CommentValue, setCommentValue] = useState();
const onHandleChange = (e) => {
setCommentValue(e.currentTarget.CommentValue);
};
// 중략
return (
<div>
<!-- 중략 -->
<textarea
style={{ width: "100%", borderRadius: "5px" }}
placeholder="코멘트를 작성해주세요."
value={CommentValue}
onChange={onHandleChange}
/>
<!-- 중략 -->
</form>
)}
</div>
);
}
export default SingleComment;
<textarea> 태그에는 덧글을 달 내용을 입력하는 곳으로 value는 useState를 사용하여 값이 실시간으로 들어가게 해준다. 그리고 onChange함수를 사용하여 변화하는 값을 CommentValue값에 똑같은 내용으로 전달되게 진행한다.
4. OnSubmit func 만들기
먼저 submit 함수를 만든다.
// client > src > components > views > VideoDetailPage > Sections > SingleComments.js
import React, { useState } from "react";
import { Comment, Avatar, Button, Input } from "antd";
const { TextArea } = Input;
function SingleComment() {
// 중략
const onHandleChange = (e) => {
setCommentValue(e.currentTarget.CommentValue);
};
const onSubmitCommnet = (e) => {
e.preventDefault();
const variables = {
content: CommentValue,
writer: user.userData._id,
postId: props.postId,
responseTo: props.comment._id,
};
Axios.post("/api/comment/saveComment", variables).then((response) => {
if (response.data.success) {
console.log(response.data.result);
props.refreshFunction(response.data.result);
setcommentValue("");
} else {
alert("덧글 저장하지 못하였습니다.");
}
});
};
// 중략
return (
<div>
<Comment
actions={actions}
author={props.comment.writer.name}
avatar={<Avatar src={props.comment.writer.image} />}
content={<p>{props.comment.content}</p>}
/>
{OpenReply && (
<form style={{ display: "flex" }} onSubmit={onSubmitCommnet}>
<textarea
style={{ width: "100%", borderRadius: "5px" }}
placeholder="코멘트를 작성해주세요."
value={CommentValue}
onChange={onHandleChange}
/>
<br />
<button
style={{ width: "20%", height: "52px" }}
onClick={onSubmitCommnet}
>
Submit
</button>
</form>
)}
</div>
);
}
export default SingleComment;
ㄹform값에서 onSubmit함수를 만든 후 해당하는 함수의 설정을 진행한다.
postId
여기서 responseTo값은 부모 컴포넌트 Comment.js에 SingleComment 태그안에서 postId값으로 상속받게 한다. 이미 Comment.js 또한 부모 컴포넌트에서 받아온 것이므로 간단하게 코드만 추가하면 된다.
// client > scr > components > views > VideoDetailPage > Sections > Comment.js
// 중략
{/* Comment Lists */}
<SingleComment postId={props.postId} />
// 중략
5. 모든 Comment 정보들을 데이터베이스에서 가져오기
가장 부모가 되는 VideoDetailPage.js에서 데이터베이스를 가져와야 하는데 먼저 API를 생성한다. 이전에 댓글을 달았던 내용들을 모두 가져오기 위해서는 다음과 같은 코드를 작성해야 한다.
// server > routes > comments.js
// 중략
router.post("/getComment", (req, res) => {
Comment.find({ postId: req.body.videoId })
.populate("writer")
.exec((err, comments) => {
if (err) return res.status(400).send(err);
res.status(200).json({ success: true, comments });
});
});
module.exports = router;
postId에 맞는 모든 comments의 정보를 가져온다.
그런 다음 VideoDetailPage.js에 다음과 같은 코드를 추가한다.
// client > src > components > views > VideoDetailPage > VideoDetailPage.js
// 중략
const [Comments, setComments] = useState([]);
useEffect(() => {
Axios.post("/api/video/getVideoDetail", videoVariable).then((response) => {
// 중략
});
Axios.post("/api/comment/getComments", videoVariable).then((response) => {
if (response.data.success) {
setComments(response.data.Comments);
console.log(response.data.Comments);
} else {
alert("덧글에 대한 정보를 가져오는 것에 실패를 하였습니다.");
}
});
}, []);
return (
{/* 중략 */}
<Comment
commentLists={Comments}
postId={videoId}
/>
{/* 중략 */}
);
// 중략
Comments에 모든 정보를 State에 배열로 가져오도록 하였다. 그리고 Comment에 prop으로 postId값을 넣어준다. 그러면 하위 컴포넌트에는 prop를 이용한 commentLists를 이용하여 Comments 이름으로 저장을 하여 받을 수 있다.
commentLists를 map함수를 이용하여 덧글을 배열형식으로 가져올 수 있게 한다.
// client > scr > components > views > VideoDetailPage > Sections > Comment.js
// 중략
{/* Comment Lists */}
{props.commentLists &&
props.commentLists.map(
(comment, index) =>
!comment.responseTo && (
<SingleComment
comment={comment}
postId={props.postId}
/>
)
)}
// 중략
그리고 다시 하위컴포넌트에 comment값을 props를 해준다.
// client > src > components > views > VideoDetailPage > Sections > SingleComments.js
import React, { useState } from "react";
import { Comment, Avatar, Button, Input } from "antd";
const { TextArea } = Input;
function SingleComment() {
// 중략
const [CommentValue, setCommentValue] = useState();
const onHandleChange = (e) => {
setCommentValue(e.currentTarget.CommentValue);
};
// 중략
return (
<div>
<Comment
actions={actions}
author={props.comment.writer.name}
avatar={<Avatar src={props.comment.writer.image} />}
content={<p>{props.comment.content}</p>}
/>
{/* 중략 */}
<div>
);
export default SingleComment;
content값과 avatar, author 등을 가져올 수 있다.
6. 저장된 댓글을 Parent Component에다가 업데이트
SingleComment와 Comment 모두가 VideoDetailPage에 comment값을 저장을 하게 되는데, 업데이트가 될 경우 자동적으로 자식 컴포넌트에도 뿌려주는 기능에 대한 코드를 작성하는 방법이다.
// client > src > components > views > VideoDetailPage > VideoDetailPage.js
// 중략
const [Comments, setComments] = useState([]);
useEffect(() => {
Axios.post("/api/video/getVideoDetail", videoVariable).then((response) => {
// 중략
});
Axios.post("/api/comment/getComments", videoVariable).then((response) => {
// 중략
}, []);
const refreshFunction = (newComment) => {
setComments(Comments.concat(newComment));
};
return (
{/* 중략 */}
<Comment
refreshFunction={refreshFunction}
commentLists={Comments}
postId={videoId}
/>
{/* 중략 */}
);
// 중략
refreshFunction으로 함수를 생성한 후 Comment 컴포넌트 안에 prop을 이용하기 위해서 refreshFunction값을 넣어준다.
'Front-End > React' 카테고리의 다른 글
ERROR : node-sass/vendor 에러 (0) | 2021.07.17 |
---|---|
지난주 삽질이야기 : API 명세서가 이렇게 중요하다. (0) | 2021.07.10 |
React-Youtube : react 덧글 기능 추가하기 (0) | 2021.05.06 |
React-Youtube : 구독페이지 만들기 (0) | 2021.05.02 |
React-Youtube : 구독 기능 UI 및 구현 (0) | 2021.04.29 |
- Total
- Today
- Yesterday
- redux
- java
- mongodb
- Visual Studio Code
- node-sass
- 프로그래머스
- 파이썬
- 뷰
- array
- 리덕스
- 리액트 유튜브
- node
- javascript
- 자바
- CSS
- react
- 자바스크립트
- 배열
- programmers
- github
- Coding Test
- 코딩테스트
- 재공부
- 리액트
- Git
- 리액트 썸네일
- Switch
- 함수
- 노드
- node.js
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |