본문 바로가기

React 수업 정리

게시판 구현해보기(2)

저번과 이어서 게시글 목록 List 페이지를 만들었으니

게시글을 생성 할 수있도록 Create 글쓰기 페이지를 만들어보도록 하자.

 

  return (
        <div className='create'>

            <h2>자유게시판 글쓰기</h2>
            <hr />
            

            <div className='container'>

                <div className='inputBox'>
                    <input className='titleInput' type="text" name='title' placeholder='제목을 입력해주세요' onChange={onChange} value={board.title}/>
                    <input className='nameInput' type="text" name='writer' placeholder='작성자' onChange={onChange} value={board.writer}/>
                </div>

                <textarea type="text" name='contents' placeholder='내용을 입력해주세요' onChange={onChange} value={board.contents}/>
                <br />
                
                <button onClick={onAdd}>등록</button>
            </div>
        </div>
    );

 

일단 화면구성을 만들어주자 제목과 작성자를 입력할 수 있도록하는 input 2개와 내용을 입력 할 수 있도록하는 textarea를

만들고 입력한 내용을 받아 바뀔 수 있도록 onChange 를 걸어두었다.

 

  const [ board , setBoard ] = useState({
        title : '',
        writer : '',
        contents : ''
    });

 

이제 보드의 상태를 정의주도록 하자 보드안에 들어가야할 내용은 auto_incre로 증가하는 id와 오늘 날짜가 자동으로 들어가는 date를 제외한 제목, 작성자, 내용 세개가 들어간다.

 

  const onChange =  (e) => {
        const { name , value } = e.target;
        setBoard({
            ...board,
            [name]:value
        });
    }

 

걸어두었던 onChange 기능을 구현해주도록하고

 

  const onAdd = async () => {

        if(board.title === ''){
            alert('제목을 입력해주세요.');
            return;
        }
        if(board.writer === ''){
            alert('작성자를 입력해주세요.');
            return;
        }
        if(board.contents === ''){
            alert('내용을 입력해주세요.');
            return;
        }
        if(window.confirm('작성하시겠습니까?')){
            try{
                await axios.post('/create', board);
                window.location.href = "/list";
            }catch(error){
                console.log(error);
            }
        }
    }

 

app.post('/create' , (req, res) => {
    
    const { title, writer, contents } = req.body;

    const sql = `insert into free_board(title, writer, contents) value (?,?,?)`;
    db.query(sql, [title,writer,contents], (err, data) => {
        if(!err){         
            res.sendStatus(200); 
        } else {
            console.log(err);
            res.send('전송오류');
        }
    });
});

글쓰기 버튼이 작동해서 데이터를 추가해서 목록에 넣을 수 있도록 구현해준다.

 


글이 작성되도록 만들었으니 안에 내용을 볼 수 있도록 title을 누르면 상세페이지로 넘어가는 detail을 만들어보자

 

디테일에는 댓글기능을 구현해보도록 하자.

댓글 기능을 위해 댓글 테이블을 따로만들고 원래 free_board table 하고 상속시켜서 연결 할 것이다.

 

CREATE TABLE comments (
    co_id INT AUTO_INCREMENT PRIMARY KEY, 
    board_id BIGINT NOT NULL,                     
    writer VARCHAR(100) NOT NULL,               
    reg_date DATETIME DEFAULT CURRENT_TIMESTAMP, 
    contents TEXT NOT NULL,                    
    FOREIGN KEY (board_id) REFERENCES free_board(id) 
);

 

댓글 테이블의 구성은 이렇게 만들어준다.

 

일단 id를 useParam()으로 받아 정의해서 각 id에 맞는 상세페이지로 들어갈 수 있도록 해주고

 

   const {id} = useParams();
   
   const [ detail , setDetail ] = useState(null);

 

받을 데이터의 상태를 정의해준다.

 

const getDetaildata = async () => {
        try{
            const board = await axios.get(`/detail/${id}`);
            setDetail(board.data[0]);
        }catch(err){
            console.log(err);
        }
    }
app.post('/detail/:id', (req, res) => {
    const id = req.params.id;
    const sql = `delete from free_board where id = ${id} `;

    db.query(sql, (err, data) => {
        if(!err){
            res.sendStatus(200); 
        } else {
            console.log(err);
            res.send('전송오류');
        }
    })
})

 

 useEffect(() => {
        getDetaildata();
    }, []);

이렇게 데이터를 받아주도록한다.

 

그리고 삭제버튼을 눌렀을 때 게시글을 삭제할 수 있도록 구현

 const onDelete = async () => {
        if(window.confirm('삭제하시겠습니까?')){
            try{
                await axios.post(`/detail/${id}`, detail);
                window.location.href = '/list';
            }catch(err){
                console.log(err);
            }
        }
    }
app.post('/detail/:id', (req, res) => {
    const id = req.params.id;
    const sql = `delete from free_board where id = ${id} `;

    db.query(sql, (err, data) => {
        if(!err){
            res.sendStatus(200); 
        } else {
            console.log(err);
            res.send('전송오류');
        }
    })
})

 

 

이러고 화면에 나오도록 구성해주면

 if(detail !== null){
        return (
            <div className='detail'>

                <div className='container'>
                    <div className='header'>
                    <a href="/list">자유게시판</a> <br />
                    <span className='title'>{detail.title}</span>
                    </div>

                    <div className='userInfo'>
                    <div>
                    <span className='writer'>{detail.writer}</span>
                    <span className='date'>({detail.reg_date.substring(0,10)})</span>    
                    </div>
                    <span className='viewCount'>조회   {detail.viewCount}</span>
                    </div>
                </div>
    
                <hr />
                <textarea name="contents" id="" readOnly>{detail.contents}</textarea>

                <div className='buttons'>
                        <div className='button1'>
                        <Link to={'/list'}><button>목록</button></Link>
                        </div>
                        <div className='button2'>
                        <Link to={`/modify/${id}`}><button className='btn1'>수정</button></Link>
                        <button onClick={onDelete}>삭제</button>      
                        </div>     
                </div>

 

이제 게시글을 눌러서 들어오면 안의 내용을 볼 수 있고 삭제버튼으로 삭제까지 할 수 있게 구현되었다.

 

여기서 댓글기능까지 넣어보도록 하자.

 

  const [writer, setWriter] = useState('');

  const [commentContent, setCommentContent] = useState(''); 

  const [comments, setComments] = useState([]);

 

먼저 댓글의 작성자, 내용, 그리고 댓글 목록의 상태를 정의해주고

 

   const getComments = async () => {
        try {
            const response = await axios.get(`/comments/${id}`);
            setComments(response.data);
        } catch (err) {
            console.log(err);
        }
    };

 

app.get('/comments/:id', (req, res) => {
    const boardId = req.params.id;
    const sql = `SELECT * FROM comments WHERE board_id = ?`;
    db.query(sql, [boardId], (err, data) => {
        if (!err) {
            res.send(data);
        } else {
            console.log(err);
            res.send('전송오류');
        }
    });
});

 

댓글의 목록을 볼 수 있도록 구현.

 

 const addComment = async () => {
        if (!writer || !commentContent) {
            alert('작성자 이름과 댓글 내용을 모두 입력하세요.');
            return;
        }
        try {
            await axios.post(`/comments/${id}`, { contents: commentContent, writer });
            setCommentContent('');
            setWriter(''); 
            getComments(); 
        } catch (err) {
            console.log(err);
        }
    };

 

 const onDeleteComment = async (commentId) => {
        if (window.confirm('댓글을 삭제하시겠습니까?')) {
            try {
                await axios.delete(`/comments/${commentId}`);
                getComments(); 
            } catch (err) {
                console.log(err);
            }
        }
    };

 

app.post('/comments/:id', (req, res) => {
    const boardId = req.params.id;
    const { writer, contents } = req.body;
    const sql = `INSERT INTO comments (board_id, writer, contents) VALUES (?, ?, ?)`;
    db.query(sql, [boardId, writer, contents], (err, data) => {
        if (!err) {
            res.sendStatus(201); // Created
        } else {
            console.log(err);
            res.send('전송오류');
        }
    });
});

app.delete('/comments/:commentId', (req, res) => {
    const commentId = req.params.commentId;
    const sql = `DELETE FROM comments WHERE co_id = ?`;
    db.query(sql, [commentId], (err, data) => {
        if (!err) {
            res.sendStatus(200); // OK
        } else {
            console.log(err);
            res.send('전송오류');
        }
    });
});

 

댓글의 추가 / 삭제도 구현해준다 여기서 삭제는 게시글 삭제할때는 post를 써보앗고 여기서는 delete를 써서 삭제해보았다.

 

    const handleKeyPress = (event) => {
        if (event.key === 'Enter') {
            addComment();
        }
    };

 

그리고 검색기능에 추가했던거처럼 엔터를 누르면 댓글등록이 가능하도록 추가해준다.

 

 <div className='comments'>
                <input 
                    className='shortInput'
                    type="text" 
                    value={writer} 
                    onChange={(e) => setWriter(e.target.value)} 
                    placeholder="작성자" 
                />
                <textarea
                    className='longText' 
                    value={commentContent}
                    onChange={(e) => setCommentContent(e.target.value)}
                    placeholder="댓글 내용을 입력하세요."
                    onKeyDown={handleKeyPress}
                />
                <button onClick={addComment}>댓글 쓰기</button>
                </div>

                <h3>댓글</h3>
                <table className='comment_table'>
                <tbody>
                    {comments.map(comment => (
                        <tr key={comment.co_id}>
                            <td>{comment.writer}</td>
                            <td>{comment.contents}
                            <button className='delBtn' onClick={() => onDeleteComment(comment.co_id)}>X</button>
                            </td>
                        </tr>
                    ))}
                </tbody>
                </table>

 

화면에 만들었던 기능들이 작동하도록 이렇게 작성한다.

 

이러면 상세페이지에서 내용을 확인하고 삭제 할 수 있으며, 댓글 기능까지 추가된걸 확인 할 수 있다.

 

댓글을 만들었더니 게시글 삭제가 작동하지않는 문제가 발생.

게시글이 삭제될 때 댓글의 데이터도 같이 삭제되도록 설정을 해주어야함.

 

app.post('/detail/:id', (req, res) => {
    const id = req.params.id;
    const deleteCommentsSql = `DELETE FROM comments WHERE board_id = ?`;
    const deleteBoardSql = `DELETE FROM free_board WHERE id = ?`;

    db.query(deleteCommentsSql, [id], (err) => {
        if (err) {
            console.log(err);
            return res.send('전송오류');
        }

        // 게시글 삭제
        db.query(deleteBoardSql, [id], (err, data) => {
            if (!err) {
                res.sendStatus(200);
            } else {
                console.log(err);
                res.send('전송오류');
            }
        });
    })
})

 

게시글과 댓글이 같이 삭제되도록 수정해주었음.


 

create / detail 페이지 완성

 

글쓰기가 잘 작동하고 상세페이지로 들어갔을 때 작성자, 제목 , 작성일 , 내용 전부 잘 나오는 걸 확인가능

삭제 시스템, 댓글 시스템 작동이 구현된걸 볼 수 있음.

 

 

 

 

 

'React 수업 정리' 카테고리의 다른 글

게시판 구현해보기(3)  (1) 2024.09.24
게시판 구현해보기(1)  (0) 2024.09.24
Board 만들어보기  (0) 2024.09.19
React 5일차  (0) 2024.09.10
React 4일차.  (3) 2024.09.09