(1) Read, Create
https://1ncomparable.tistory.com/204
💛 게시글 삭제하기 (Delete)
서버
라우터 (discussions.js)
router.delete("/:id", deleteDiscussion);
컨트롤러
deleteDiscussion: (req, res) => {
const idx = discussionsData.findIndex(
(data) => data.id === Number(req.params.id)
); // 파라미터의 id 와 일치하는 데이터의 인덱스 찾기
if (idx !== -1) {
// 인덱스가 있으면 = 삭제해야할 데이터가 존재하면
discussionsData.splice(idx, 1); // 데이터 배열에서 인덱스번째에서 1개 요소 제거 = 인덱스번째의 요소 제거
return res.status(204).send("resource deleted successfuly");
} else {
// 삭제해야할 데이터가 없으면 404 리턴
return res.status(404).send("Not found");
}
},
클라이언트
App.js에서 deleteData 함수를 작성하고 props로 컴포넌트인 Discussion.js에 내려주었다. 그리고 컴포넌트에서 추가한 삭제버튼에 이벤트를 추가했다.
const deleteData = (id) => {
setIsChanged(true);
return fetch(`${url}/${id}`, {
method: "DELETE",
});
};
변화가 생길때 useEffect의 콜백함수를 실행하기 위해 isChanged의 상태를 변경한다.
중간에 delete 요청할 id를 요청 body에 담아 보내주는 바람에 큰 에러가 생겼었다. 사실은 파라미터로 해결할 수 있는 부분이었었는데... 그것때문에 시간이 조금 걸렸다. 이 부분을 구현하면서 HTTP 메서드를 좀 더 자세히 알아봐야할것같다고 느꼈다. 어떤 메서드에 본문이 반드시 필요한지, 또는 특정 메서드에 본문을 같이 보내야 하는 경우는 어떤것인지 좀더 이해해야할거같다.
💚 게시글 수정하기 (Update)
서버
컨트롤러에 아래의 코드를 추가했다.
updateDiscussion: (req, res) => {
const idx = discussionsData.findIndex(
(data) => data.id === Number(req.params.id)
);
const updatedData = {
...discussionsData[idx],
...req.body,
};
if (idx !== -1) {
discussionsData.splice(idx, 1, updatedData);
}
return res.status(200).send("resource updated successfuly");
},
클라이언트
App.js에 PUT 요청을 보낼 함수를 작성한다.
const putData = (id, title, updatedAt) => {
const updatedData = {
id,
title,
updatedAt,
};
return fetch(url + `/${id}`, {
method: "PUT",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(updatedData),
}).then(() => getData());
};
DiscussionList와 Discussion에 putData를 props로 내려주고 Discussion 컴포넌트에 수정된 내용을 위한 코드를 작성한다.
작성한 내용은 다음과 같다.
- 게시글의 제목 클릭시 수정가능한 textarea 나타남
- textarea에 수정한 내용 작성후 엔터를 치면 이벤트 실행
- 수정된 제목과 수정한 날짜 및 시간으로 게시글이 변경됨
import { useState } from "react";
const Discussion = ({ data, deleteData, putData }) => {
const [isEdit, setIsEdit] = useState(false); // 수정모드
const [editTxt, setEditTxt] = useState(data.title); // 수정한 텍스트
const handleChangeEditTxt = (event) => {
setEditTxt(event.target.value);
};
const editTitle = (event, id, title) => { // textarea에서 엔터키 쳤을때 실행되는 이벤트
if (event.key === "Enter") { // 입력된 키가 엔터이면
const updatedAt = new Date().toISOString();
putData(id, title, updatedAt);
setIsEdit(false);
setEditTxt(data.title);
}
};
return (
// ....
<div className="discussion__content">
{isEdit ? (
<textarea
type="text"
value={editTxt}
onChange={handleChangeEditTxt}
onKeyUp={(event) => editTitle(event, data.id, editTxt)}
/>
) : (
<h2 className="discussion__title" onClick={() => setIsEdit(true)}>
{data.title}
</h2>
)}
<div className="discussion__information">
{`${data.author} / ` + data.createdAt !== data.updatedAt
? parseDate(data.updatedAt)
: parseDate(data.createdAt)}
</div>
</div>
// ....
);
};
수정모드를 나타낼 isEdit와 수정된 텍스트를 저장해둘 editTxt state를 만들어주었다.
editTitle은 textarea에 엔터키가 입력되었을때 실행될 이벤트이다. 인자로는 event, id, title이 들어오고, 여기서 props로 받은 putData 함수를 실행하며 인자를 넘겨준다. 동시에 isEdit과 editTxt의 내용을 초기화시킨다.
div.discussion__content를 보면 isEdit가 true일때 제목을 수정할 수 있는 textarea가 나타나게 해두었다. textarea에는 onchange, onKeyUp(키를 눌렀다 떼었을때 이벤트 실행) 이벤트가 걸려있다.
discussion__title에는 클릭시 isEdit을 true로 바꾸는 onClick 이벤트가 설정되어 있다.
게시글의 제목이 수정되면 나타나는 날짜도 바뀌어야한다. discussion__information에서는 data의 createdAt과 updatedAt이 다를 경우 updatedAt이 나타나도록 설정했다.
***********
내일은 fetch로 받아오던 데이터들을 axios로 받아오도록 수정할 것이다.
아직 이... 미니 프로젝트를 (미니 프로젝트라고 해도 되는지 모르겠다 기능이 너무 없어서 흑흑) 다 완성한건 아니지만 그래도 몇가지 느낒넘이 있다.
1. css class name이나 여러 이름들에 대한 컨벤션이 필요함
2. 깃 커밋 메시지를 한눈에 알아볼수있게 작성하자(커밋메시지 컨벤션이 있는지 알아보기)
3. 깃 리드미를 작성해서 미니미니미니.. 아무튼 엄청 작은 프로젝트라도 내가 왜 이 프로젝트를 했고 무엇을 만들었고 무엇을 아쉬워하는지, 또 최종적으로는 무엇을 느꼈는지 간결하게 볼 수 있게 하자.
4. 커밋은 자주하자 (근데 얼마정도로 자주해야하는지 아직 감이 잘 안온다)
이 프로젝트를 마무리 하게 되면 짧은 회고를 통해 정리해보려고한다.
내일도 힘내자 아무튼!
'study > React' 카테고리의 다른 글
[React] HTML과 다른 Attributes (0) | 2023.02.27 |
---|---|
[React] 바닐라 JS 게시판 리팩토링 (3) - axios (0) | 2023.02.18 |
[React] 바닐라 JS 게시판 리팩토링 (1) - Read, Create (0) | 2023.02.11 |
[React] 미니 트위터 클론코딩(CRUD) (0) | 2023.01.31 |
[React] Fragment (0) | 2023.01.27 |