저번과 이어서 게시글 목록 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 |