
게시물 목록에서 특정 게시물의 삭제 버튼을 누르면 해당 글이 삭제되는 기능 구현 중 이 같은 에러가 발생하였다.
데이터베이스에서 게시물 데이터를 삭제하려면 해당 게시물의 id값을 넘겨줘야 어떤 항목을 삭제할지 알 수 있으므로, 위와 같이 request body에 id를 넘겨주려 시도하였다. 서버에 Object나 Array를 넘겨줄 때는 JSON.stringify()를 사용하여 문자열 형식으로 보내줘야 하기 때문에 저렇게 작성한 것이었는데, 이 부분(정확히는 해당 요청을 받는 부분)에서 문제가 발생한 것을 알게 되었다.
// /app/list/ListItem.js
export default function ListItem({ data }) {
return (
// ...
<button
onClick={() =>
fetch("/api/post/delete", {
method: "DELETE",
body: JSON.stringify({ _id: data._id}),
}).then(() => {
console.log("테스트");
}).catch((error) => {
console.error("에러:", error);
})
// ...
}>
// /pages/api/post/delete.js
export default async function handler(request, response) {
if (request.method == "DELETE") {
console.log(request.body);
try {
const db = (await connectDB).db("forum");
const filter = { _id: new ObjectId(request.body._id) }
const data = await db.collection("post").deleteOne(filter);
return response.status(200).json(data + "삭제");
} catch (error) {
return response.status(500).json("DB 삭제 실패");
}
}
}
에러 문구를 해석해보면
Only plain objects can be passed to Client Components from Server Components. Objects with toJSON methods are not supported. Convert it manually to a simple value before passing it to props.
클라이언트 컴포넌트에서 서버 컴포넌트로 전달 시 plain object만 가능하며, JSON으로 변환해주는 메소드를 지원하지 않으니, props로 전달하기 이전에 단순한 데이터(문자열 혹은 숫자 등)으로 직접 바꾸라고 하고 있다.
내 코드에서는 plain object가 아닌 ObjectId 객체를 서버에 전달하고 있음으로, 해당 오류가 뜬 것 같다.
이에 대해 두 가지 해결 방안이 존재한다.
1.
애초에 서버 컴포넌트로 게시물의 id값을 넘겨줄 때, { _id: data._id } 와 같이 객체를 그대로 넘겨줄게 아니라 단순히 id값만(data._id) 전달해주면 된다.
fetch("/api/post/delete", {
method: "DELETE",
body: data._id,
})
실제로 이렇게 전달 시 요청을 받은 서버에서는 request.body를 콘솔에 찍어봤을 때 선택한 게시물 데이터의 id값이 출력되는 것을 확인할 수 있다.
2.
서버에 object나 array를 보낼 때는 JSON.stringify()를 사용하라고 했다. (서버와 데이터를 주고 받을 때는 문자나 숫자만 가능하기 때문)
해당 메소드 사용 시 원래 object가 { _id: 123 } 이었다고 할 때, JSON.stringify({ _id: 123 })는
{ "_id": 123 }
이와 같이 JSON 형식으로 변환된다.
따라서, . 연산자를 사용하여 객체의 값에 접근하는 것이 불가능해진다.
1번 방법과 다르게 나는 그냥 보낼 때 object형으로 보내고, 받을 때 request.body._id 해서 받으면 되는거 아니야?라고 생각할 수 있는데, 그게 불가능하다는 뜻이다.
고로 서버에 전달될 때 JSON형으로 바꿨던 데이터를 다시 Object형으로 바꿔주어야 하는데, 이는 JSON.parse()를 사용하면 된다.
결과적으로 JSON.parse(request.body)._id 와 같이 작성하면 ObjectId를 보내도 그 안에서 id값만 뽑아내어 사용할 수는 있게 되는 것이다. (고로 처음에 작성했던 대로 요청을 보내려면 서버 컴포넌트에서의 코드를 아래와 같이 수정해줘야 된다)
// 서버에 요청 시 데이터도 함께 전달
fetch("/api/post/delete", {
body: JSON.stringify({ _id: data._id}),
})
// 서버 컴포넌트에서 요청을 받을 때
const data = await db.collection("post").deleteOne(JSON.parse(request.body)._id);
참고 :
Warning: Only plain objects can be passed to Client Components from Server Components.
errWarning: Only plain objects can be passed to Client Components from Server Components.클라이언트 컴포넌트에 plain object가 아닌 객체(예: ObjectId 객체)를 전달하려고 했기 때문에
velog.io

게시물 목록에서 특정 게시물의 삭제 버튼을 누르면 해당 글이 삭제되는 기능 구현 중 이 같은 에러가 발생하였다.
데이터베이스에서 게시물 데이터를 삭제하려면 해당 게시물의 id값을 넘겨줘야 어떤 항목을 삭제할지 알 수 있으므로, 위와 같이 request body에 id를 넘겨주려 시도하였다. 서버에 Object나 Array를 넘겨줄 때는 JSON.stringify()를 사용하여 문자열 형식으로 보내줘야 하기 때문에 저렇게 작성한 것이었는데, 이 부분(정확히는 해당 요청을 받는 부분)에서 문제가 발생한 것을 알게 되었다.
// /app/list/ListItem.js
export default function ListItem({ data }) {
return (
// ...
<button
onClick={() =>
fetch("/api/post/delete", {
method: "DELETE",
body: JSON.stringify({ _id: data._id}),
}).then(() => {
console.log("테스트");
}).catch((error) => {
console.error("에러:", error);
})
// ...
}>
// /pages/api/post/delete.js
export default async function handler(request, response) {
if (request.method == "DELETE") {
console.log(request.body);
try {
const db = (await connectDB).db("forum");
const filter = { _id: new ObjectId(request.body._id) }
const data = await db.collection("post").deleteOne(filter);
return response.status(200).json(data + "삭제");
} catch (error) {
return response.status(500).json("DB 삭제 실패");
}
}
}
에러 문구를 해석해보면
Only plain objects can be passed to Client Components from Server Components. Objects with toJSON methods are not supported. Convert it manually to a simple value before passing it to props.
클라이언트 컴포넌트에서 서버 컴포넌트로 전달 시 plain object만 가능하며, JSON으로 변환해주는 메소드를 지원하지 않으니, props로 전달하기 이전에 단순한 데이터(문자열 혹은 숫자 등)으로 직접 바꾸라고 하고 있다.
내 코드에서는 plain object가 아닌 ObjectId 객체를 서버에 전달하고 있음으로, 해당 오류가 뜬 것 같다.
이에 대해 두 가지 해결 방안이 존재한다.
1.
애초에 서버 컴포넌트로 게시물의 id값을 넘겨줄 때, { _id: data._id } 와 같이 객체를 그대로 넘겨줄게 아니라 단순히 id값만(data._id) 전달해주면 된다.
fetch("/api/post/delete", {
method: "DELETE",
body: data._id,
})
실제로 이렇게 전달 시 요청을 받은 서버에서는 request.body를 콘솔에 찍어봤을 때 선택한 게시물 데이터의 id값이 출력되는 것을 확인할 수 있다.
2.
서버에 object나 array를 보낼 때는 JSON.stringify()를 사용하라고 했다. (서버와 데이터를 주고 받을 때는 문자나 숫자만 가능하기 때문)
해당 메소드 사용 시 원래 object가 { _id: 123 } 이었다고 할 때, JSON.stringify({ _id: 123 })는
{ "_id": 123 }
이와 같이 JSON 형식으로 변환된다.
따라서, . 연산자를 사용하여 객체의 값에 접근하는 것이 불가능해진다.
1번 방법과 다르게 나는 그냥 보낼 때 object형으로 보내고, 받을 때 request.body._id 해서 받으면 되는거 아니야?라고 생각할 수 있는데, 그게 불가능하다는 뜻이다.
고로 서버에 전달될 때 JSON형으로 바꿨던 데이터를 다시 Object형으로 바꿔주어야 하는데, 이는 JSON.parse()를 사용하면 된다.
결과적으로 JSON.parse(request.body)._id 와 같이 작성하면 ObjectId를 보내도 그 안에서 id값만 뽑아내어 사용할 수는 있게 되는 것이다. (고로 처음에 작성했던 대로 요청을 보내려면 서버 컴포넌트에서의 코드를 아래와 같이 수정해줘야 된다)
// 서버에 요청 시 데이터도 함께 전달
fetch("/api/post/delete", {
body: JSON.stringify({ _id: data._id}),
})
// 서버 컴포넌트에서 요청을 받을 때
const data = await db.collection("post").deleteOne(JSON.parse(request.body)._id);
참고 :
Warning: Only plain objects can be passed to Client Components from Server Components.
errWarning: Only plain objects can be passed to Client Components from Server Components.클라이언트 컴포넌트에 plain object가 아닌 객체(예: ObjectId 객체)를 전달하려고 했기 때문에
velog.io