문제의 근원은 이런 식 이었다.
Read/[id]/page.jsx에서 넘어오는 서버데이터를 하위 컴포넌트인 ReadContent.jsx에 props로 전달해, 특히 게시글의 id 등을 적재적소에 전달하기 위한 로직이 너무 복잡했고, 그 복잡함 속에서 정말 큰 위기가 있었다. 오늘은 이 이야기를 해보려 한다.
1. 코멘트 수정 서버 통신 이벤트를 핸들링 하는 버튼이, map()으로 그려지는 div의 바깥에 있었다. 분명히 같은 함수로 들어오고 있는데, 그 데이터의 배열을 자유롭게 쓸 수가 없어서 큰 문제가 된 것이다.
(...) // commentList === [];
const ReadContent = (commentList) => {
const updateComment = async () => {
// 수정 작업을 서버에 업데이트 하는 곳이 여긴데, commentList[i]의 id를 추출할 수 없어서 undefined만 들어오는 상황. api 무용지물 대환장 파티.
}
}
(...)
return (
{commentsList.map((comment) => {
// 여기서 사용되는 삭제 이벤트 핸들러는 map으로 분해된 데이터를 바로 가져 오기 때문에, 사용할 수 있었다.
}}
)
2. 실력이 좋은 동료의 도움을 받았다. 먼저, 기존의 toggle 로직을 그대로 가지고 있으면서, map() 내부에서 데이터 값을 담고 돌아올 수 있는 함수를 선언했다.
// 수정하려는 코멘트의 ID 값 저장을 위한 State 추기
const [commentId, setCommentId] = useState();
const toggleAndSetCommentId = (commentId) => {
setIsEditing(!isEditing);
setCommentId(commentId);
};
(...)
<St.Button
buttontheme="secondary"
onClick={() => deleteComment(comment.id)}
style={{
width: "50px",
height: "20px",
margin: "7px 0 0 7px",
}}
>
✖︎
</St.Button>
<St.Button
buttontheme="secondary"
// 그리고 여기서 comment.id를 인자로 넘겨주게 되며, map() 바깥으로 이 데이터를 구출한다.
onClick={() => toggleAndSetCommentId(comment.id)}
style={{
width: "50px",
height: "20px",
margin: "7px 0 7px 7px",
fontWeight: "bold",
}}
>
✚
</St.Button>
3. 데리고 나간 인자에 담긴 데이터를 이벤트 핸들러에 가져왔다.
const updateComment = async () => {
try {
const res = await axios.put(
// 정상 동작!!!
`/api/posts/${id}/comments/${commentId}`,
{ comment: editedComment },
{
headers: {
"Content-Type": "application/json",
Authorization: `${token}`,
},
withCredentials: true,
}
);
if (res.status === 200) {
setIsEditing(false);
console.log(res);
}
} catch (error) {
console.error(error);
}
};