[ react ] 댓글추가하기

Suji Kang·2023년 11월 9일
0
post-custom-banner

🐾 댓글추가하기

📌 반복되는부분(작성일, 수정일은) 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')
;


📌 1. props로 받아줌 (activityDetails.js에서)

📌 2. useEffect로 댓글목록 가져온다.

📌 3. api get 요청


📝 1. props로 받아줌

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;

📝 2. useEffect로 댓글목록 가져온다.

주소에다가 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;

리액트가 전달해준 게시글 번호

📝 3. api get 요청

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...🌟

profile
나를위한 노트필기 📒🔎📝
post-custom-banner

0개의 댓글