클론코딩
[인프런] 유튜브 사이트 만들기 (3)
cmkoi1
2023. 1. 22. 15:26
따라하며 배우는 노드, 리액트 시리즈 - 유튜브 사이트 만들기 강의
[무료] 따라하며 배우는 노드, 리액트 시리즈 - 유튜브 사이트 만들기 - 인프런 | 강의
이 강의를 통해 리액트와 노드의 개념을 익히는 것뿐만이 아닌 실질적으로 어떻게 웹사이트를 만들 수 있는지를 배울 수 있습니다., - 강의 소개 | 인프런...
www.inflearn.com
※ 해당 링크 강의 내용을 바탕으로 작성된 포스팅입니다.
좋아요 싫어요 기능 생성 (1) 구조 설명
1. Like & DisLike Model 만들기
- boilerplate-mern-stack-master\server\models 경로에 Like.js 파일과 Dislike.js 파일 생성.
Like.js
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const likeSchema = mongoose.Schema({
userId: {
type: Schema.Types.ObjectId,
ref: 'User'
},
commentId: {
type: Schema.Types.ObjectId,
ref: 'Comment'
},
videoId: {
type: Schema.Types.ObjectId,
ref: 'Video'
}
}, { timestamps: true }) //만든날과 업데이트날 표시
const Like = mongoose.model('Like', likeSchema);
module.exports = { Like }
Dislike.js
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const dislikeSchema = mongoose.Schema({
userId: {
type: Schema.Types.ObjectId,
ref: 'User'
},
commentId: {
type: Schema.Types.ObjectId,
ref: 'Comment'
},
videoId: {
type: Schema.Types.ObjectId,
ref: 'Video'
}
}, { timestamps: true }) //만든날과 업데이트날 표시
const Dislike = mongoose.model('Dislike', dislikeSchema);
module.exports = { Dislike }
2. 구조 설명
좋아요 싫어요 기능 (2) 템플릿, 데이터 가져오기
1. AntD을 이용하여 Like & Dislike 버튼 만들기
VideoDetailPage.js
import LikeDislikes from './Sections/LikeDislikes';
<List.Item
actions={[ <LikeDislikes />, subcribeButton ]}
>
- boilerplate-mern-stack-master\client\src\components\views\VideoDetailPage\Sections 경로에 LikeDislikes.js 파일 생성.
LikeDislikes.js
import React from 'react'
import { Tooltip, Icon } from 'antd';
function LikeDislikes() {
return (
<div>
<span key="comment-basic-like">
<Tooltip title="Like">
<Icon type="like"
theme="filled"
onClick
/>
</Tooltip>
<span style={{ paddingLeft:'8px', cursor:'auto' }}> 1 </span>
</span>
<span key="comment-basic-dislike">
<Tooltip title="Dislike">
<Icon type="dislike"
theme="outlined"
onClick
/>
</Tooltip>
<span style={{ paddingLeft:'8px', cursor:'auto' }}> 1 </span>
</span>
</div>
)
}
export default LikeDislikes
2. DB에서 현재 좋아요 싫어요에 대한 정보 가져오기
- 좋아요 싫어요 정보가 비디오에 대한 것인지, 댓글에 대한 것인지 나눠 줘야 한다. 따라서, Request 보낼 때 변수는 Video와 Comment가 달라야 한다.
VideoDetailPage.js
<List.Item
actions={[ <LikeDislikes video userId={localStorage.getItem('userId')} videoId={videoId} />, subcribeButton ]}
>
SingleComment.js
import LikeDislikes from './LikeDislikes';
const actions = [
<LikeDislikes userId={localStorage.getItem('userId')} commentId={props.comment._id} />,
<span onClick={onClickReplyOpen} key="comment-basic-reply-to">Reply to</span>
]
LikeDislikes.js
import Axios from 'axios';
function LikeDislikes(props) {
let variable = { } //비디오에 대한 거면 videoId, 댓글에 대한 거면 commentId
if(props.video) {
variable = { videoId: props.videoId, userId: props.userId }
} else {
variable = { commentId: props.commentId, userId: props.userId }
}
useEffect(() => {
Axios.post('/api/like/getLikes', variable )
.then(response => {
if(response.data.success) {
} else {
alert('Likes에 대한 정보를 가져오지 못했습니다.')
}
})
Axios.post('/api/like/getDislikes', variable )
.then(response => {
if(response.data.success) {
} else {
alert('DisLikes에 대한 정보를 가져오지 못했습니다.')
}
})
}, [])
- boilerplate-mern-stack-master\server\routes 경로에 like.js 파일 생성 및 comment.js 파일 내용 복사 후 수정.
like.js
const express = require('express');
const router = express.Router();
const { Like } = require("../models/Like");
const { Dislike } = require("../models/Dislike");
//=================================
// Like
//=================================
router.post("/getLikes", (req, res) => {
let variable = {}
if(req.body.videoId) {
variable = { videoId: req.body.videoId }
} else {
variable = { commentId: req.body.commentId }
}
Like.find(variable)
.exec((err, likes) => {
if(err) return res.status(400).send(err)
res.status(200).json({ success: true, likes })
})
});
router.post("/getDislikes", (req, res) => {
let variable = {}
if(req.body.videoId) {
variable = { videoId: req.body.videoId }
} else {
variable = { commentId: req.body.commentId }
}
Dislike.find(variable)
.exec((err, dislikes) => {
if(err) return res.status(400).send(err)
res.status(200).json({ success: true, dislikes })
})
});
module.exports = router;
index.js
app.use('/api/like', require('./routes/like'));
2-1. 좋아요 싫어요 수와 좋아요나 싫어요 둘 중 하나 클릭 여부
LikeDislikes.js
function LikeDislikes(props) {
const [Likes, setLikes] = useState(0)
const [Dislikes, setDislikes] = useState(0)
const [LikeAction, setLikeAction] = useState(null)
const [DisLikeAction, setDisLikeAction] = useState(null)
useEffect(() => {
Axios.post('/api/like/getLikes', variable )
.then(response => {
if(response.data.success) {
// 받은 좋아요 수
setLikes(response.data.likes.length)
// 내가 누른 좋아요 유무
response.data.likes.map(like => {
if(like.userId === props.userId) { //비디오나 코멘트의 모든 like와 내가 누른 like가 같으면
setLikeAction('liked')
}
})
} else {
alert('Likes에 대한 정보를 가져오지 못했습니다.')
}
})
Axios.post('/api/like/getDislikes', variable )
.then(response => {
if(response.data.success) {
// 받은 싫어요 수
setDislikes(response.data.dislikes.length)
// 내가 누른 싫어요 유무
response.data.dislikes.map(dislike => {
if(dislike.userId === props.userId) { //비디오나 코멘트의 모든 dislike와 내가 누른 dislike가 같으면
setDisLikeAction('disliked')
}
})
} else {
alert('DisLikes에 대한 정보를 가져오지 못했습니다.')
}
})
}, [])
2.2 기타 수정 사항
LikeDislikes.js
<Icon type="like"
theme={LikeAction === 'liked'? 'filled' : 'outlined'}
onClick
/>
<span style={{ paddingLeft:'8px', cursor:'auto' }}> {Likes} </span>
<Icon type="dislike"
theme={DisLikeAction === 'disliked'? 'filled' : 'outlined'}
onClick
/>
<span style={{ paddingLeft:'8px', cursor:'auto' }}> {Dislikes} </span>
좋아요 싫어요 기능 (3) 클릭시 기능들
1. onLike func 만들기
LikeDislikes.js
const onLike = () => {
if(LikeAction === null) { //좋아요 클릭 안 되어있을 때
Axios.post('/api/like/upLike', variable)
.then(response => {
if(response.data.success) {
setLikes(Likes +1)
setLikeAction('liked')
if(DisLikeAction !== null ) { //싫어요가 클릭되어 있었을경우
setDisLikeAction(null)
setDislikes(Dislikes -1)
}
} else {
alert('Like를 올리지 못했습니다.')
}
})
} else { //좋아요가 클릭 되어 있을 때
Axios.post('/api/like/unLike', variable)
.then(response => {
if(response.data.success) {
setLikes(Likes -1)
setLikeAction(null)
} else {
alert('Like를 내리지 못했습니다.')
}
})
}
}
<Icon type="like"
theme={LikeAction === 'liked'? 'filled' : 'outlined'}
onClick={onLike}
/>
like.js
router.post("/upLike", (req, res) => {
let variable = {}
if(req.body.videoId) { //비디오 혹은 코멘트 아이디와 유저 아이디가 매칭되어야 함
variable = { videoId: req.body.videoId, userId: req.body.userId }
} else {
variable = { commentId: req.body.commentId, userId: req.body.userId }
}
//Like collection에다가 클릭 정보 넣기
const like = new Like(variable)
like.save((err, likeResult) => {
if(err) return resjson({ success: false, err })
//Dislike가 이미 클릭되었을 때, Dislike 1 줄이기
Dislike.findOneAndDelete(variable)
.exec((err, disLikeResult) => {
if(err) return res.status(400).json({ success: false, err })
res.status(200).json({ success: true })
})
})
});
router.post("/unLike", (req, res) => {
let variable = {}
if(req.body.videoId) {
variable = { videoId: req.body.videoId, userId: req.body.userId }
} else {
variable = { commentId: req.body.commentId, userId: req.body.userId }
}
Like.findOneAndDelete(variable)
.exec((err, result) => {
if(err) return res.status(400).json({ success: false, err })
res.status(200).json({ success: true })
})
});
2. onDisLike func 만들기
LikeDislikes.js
const onDisLike = () => {
if(DisLikeAction !== null) {
Axios.post('/api/like/unDislike', variable)
.then(response => {
if(response.data.success) {
setDislikes(Dislikes -1)
setDisLikeAction(null)
} else {
alert('dislike를 지우지 못했습니다.')
}
})
} else {
Axios.post('/api/like/upDislike', variable)
.then(response => {
if(response.data.success) {
setDislikes(Dislikes +1)
setDisLikeAction('disliked')
if(LikeAction !== null) {
setLikeAction(null)
setLikes(Likes -1)
}
} else {
alert('dislike를 지우지 못했습니다.')
}
})
}
}
<Icon type="dislike"
theme={DisLikeAction === 'disliked'? 'filled' : 'outlined'}
onClick={onDisLike}
/>
like.js
router.post("/unDislike", (req, res) => {
let variable = {}
if(req.body.videoId) {
variable = { videoId: req.body.videoId, userId: req.body.userId }
} else {
variable = { commentId: req.body.commentId, userId: req.body.userId }
}
Dislike.findOneAndDelete(variable)
.exec((err, result) => {
if(err) return res.status(400).json({ success: false, err })
res.status(200).json({ success: true })
})
});
router.post("/upDislike", (req, res) => {
let variable = {}
if(req.body.videoId) {
variable = { videoId: req.body.videoId, userId: req.body.userId }
} else {
variable = { commentId: req.body.commentId, userId: req.body.userId }
}
//Dislike collection에다가 클릭 정보 넣기
const dislike = new Dislike(variable)
dislike.save((err, likeResult) => {
if(err) return resjson({ success: false, err })
//Like가 이미 클릭되었을 때, Like 1 줄이기
Like.findOneAndDelete(variable)
.exec((err, likeResult) => {
if(err) return res.status(400).json({ success: false, err })
res.status(200).json({ success: true })
})
})
});
수정해야 하는 것
- 비회원 댓글 작성 오류
- 새로고침 시 3 Depth 댓글 사라지는 오류
728x90