📌 반복되는부분(작성일, 수정일은) map함수 사용👇
activityCommentSection.js
<CommentListWrap>
{
commentList.map((comment)=> <CommentItem>
<CommentHeader>
<CommentWriter>
작성자 id : {comment.writer_email}
</CommentWriter>
<CommentDate>(작성일){comment.created_date}</CommentDate>
<CommentDate>(수정일){comment.updated_date}</CommentDate>
{comment.owner && <CommentBtn>삭제</CommentBtn>}
</CommentHeader>
<Comment>{comment.content}</Comment>
</CommentItem>)
}
</CommentListWrap>
sql
create table tbl_comments(
id int auto_increment primary key,
content text not null,
activity_id int references tbl_activities (id),
created_date datetime default now(),
updated_date datetime default now(),
writer_email varchar(30) references tbl_users (email)
);
dummy data
insert into tbl_comments
(content, activity_id, writer_email)
values
('안녕', 1, '123@test.com'),
('안녕반가워', 2, '123@test.com'),
('안녕', 3, '123@test.com'),
('안녕', 4, '123@test.com'),
('안녕', 5, '123@test.com')
;
activityDetails.js
const ActivityDetailPage = ()=>{
useAuth();
const params = useParams();
// console.log(params);
return(
<DashboardLayout target="활동게시판">
<h1>{params.id}번 게시글 상세 페이지</h1>
<ActivityDetailSection activityId={params.id}/>
<ActivityCommentSection activityId={params.id}/>
//🌟 props로 activityId보내줌.
</DashboardLayout>
);
}
export default ActivityDetailPage;
주소에다가
activityId
로 넘겨준다. (위치는 🌟 참조)
정상적으로 받아오면 목록 comment state 변수도 만든다.
받은것 map함수로 보여준다.
activityCommentSection.js
import { useEffect, useState } from "react";
import { Comment, CommentBtn, CommentDate, CommentHeader, CommentInput, CommentInputWrap, CommentItem, CommentListWrap, CommentWriteBtn, CommentWriter } from "../../styles/dashboard/activityComment.styles";
import axios from "axios";
const ActivityCommentSection = (props)=>{
const [commentList, setCommentList] = useState([]);
useEffect(()=>{
let tmp = async ()=>{
try{
let res = await axios.get(`/api/comments?activityId=${props.activityId}`, {
//🌟 주소에다가 activityId로 넘겨준다.
setCommentList(res.data); //데이터로부터 받아온것을 setCommentList로 바꿔줘
}catch(err){
alert('댓글목록 오류');
}
}
tmp();
}, [props.activityId]);
return(
<section>
<CommentInputWrap>
<CommentInput/>
<CommentWriteBtn>댓글달기</CommentWriteBtn>
</CommentInputWrap>
<CommentListWrap>
{
commentList.map((comment)=> <CommentItem>
<CommentHeader>
<CommentWriter>
작성자 id : {comment.writer_email}
</CommentWriter>
<CommentDate>(작성일){comment.created_date}</CommentDate>
<CommentDate>(수정일){comment.updated_date}</CommentDate>
{comment.owner && <CommentBtn>삭제</CommentBtn>}
</CommentHeader>
<Comment>{comment.content}</Comment>
</CommentItem>)
}
</CommentListWrap>
</section>
);
}
export default ActivityCommentSection;
리액트가 전달해준 게시글 번호
query
안에activityId
를 받아옴 (위치 🌟 참조)
orderby
최신순으로 설정
app.js
app.get('/api/comments', async (req, res) => {
const activityId = Number(req.query.activityId);
//activityId받기. 🌟 문자타입이니까 숫자타입으로 바꿔줘야함 Number 사용해서
try {
const token = req.headers.authorization.replace('Bearer ', '');
let user = jwt.verify(token, process.env.JWT_SECRET);
let [results] = await pool.query('select * from tbl_comments where activity_id = ? order by created_date asc', [activityId])
//👉 sql쿼리 작성
results = results.map((el) => ({ ...el, owner: el.writer_email === user.email }));
console.log(results);
res.json(results);
} catch (err) {
res.status(500).json('오류발생');
}
})
그런데, 로그인한사람만 수정하기랑 삭제하기를 할수있어야한다. accessToken필요, 받은다음에 express한테 전달해야함.
activityCommentSection.js
import { useContext, useEffect, useState } from "react";
import { Comment, CommentBtn, CommentDate, CommentHeader, CommentInput, CommentInputWrap, CommentItem, CommentListWrap, CommentWriteBtn, CommentWriter } from "../../styles/dashboard/activityComment.styles";
import axios from "axios";
import { UserContext } from "../../App";
const ActivityCommentSection = (props)=>{
const [commentList, setCommentList] = useState([]);
const {accessToken} = useContext(UserContext); //accessToken가져옴
useEffect(()=>{
let tmp = async ()=>{
if(accessToken === null) return; //accessToken === null 이면 바로 종료.
try{
let res = await axios.get(`/api/comments?activityId=${props.activityId}`, {
headers:{Authorization:`Bearer ${accessToken}`}
})
//accessToken 넣어서 express 로 전달
setCommentList(res.data);
}catch(err){
alert('댓글목록 오류');
}
}
tmp();
}, [props.activityId, accessToken]);
// accessToken이 null 이 였다가 바뀌면, 함수가 다시 실행되어야함
}
export default ActivityCommentSection;
token 받음 그리고, jwt.verify해서 해독한다.
요소를 만들어서 객체를 만든다
댓글인데 배열 2개 들어감.
app.js
app.get('/api/comments', async (req, res) => {
const activityId = Number(req.query.activityId);
try {
const token = req.headers.authorization.replace('Bearer ', '');
let user = jwt.verify(token, process.env.JWT_SECRET);
let [results] = await pool.query('select * from tbl_comments where activity_id = ? order by created_date asc', [activityId])
} catch (err) {
res.status(500).json('오류발생');
}
})
🔎 results 기존에 있는 배열에서,
owner이면, 원래 요소들 다 나오고,( email정보로 확인 )
app.js
results = results.map((el) => ({ ...el, owner: el.writer_email === user.email }));
//원래 자기 자신 요소, 요소안에있는 writer_email하고 user.email가 같으면.
//객체를 만든 중괄호
console.log(results);
res.json(results);
🔎 owner이면, 삭제가능
actvityCommentSection.js
{comment.owner && <CommentBtn>삭제</CommentBtn>}
activityComment.styles.js
import styled from "@emotion/styled";
export const CommentInputWrap = styled.div`
display: flex;
margin-top: 20px;
`;
export const CommentDate = styled.div`
margin: 0 5px;
`
export const CommentInput = styled.input`
flex-basis: 80%;
border: 1px solid silver;
padding: 20px;
`;
export const CommentWriteBtn = styled.button`
flex-basis: 20%;
background-color: black;
color: white;
border: none;
cursor: pointer;
`;
export const CommentListWrap = styled.div`
border-top: 1px solid black;
border-bottom: 1px solid black;
margin-top: 10px;
`;
export const CommentItem = styled.div`
border-bottom: 1px solid silver;
padding: 10px;
`;
export const CommentHeader = styled.div`
display: flex;
padding:10px 0;
align-items: center;
`;
export const CommentWriter = styled.div`
flex-grow: 1;
`;
export const CommentBtn = styled.button`
flex-grow: 0;
cursor: pointer;
margin: 0 10px;
padding: 2px 10px;
`;
export const Comment = styled.div`
`;
to be continued...🌟