🌞 MongoDB 데이터 수정하기
await db.collection('콜렉션이름').updateOne( {게시물정보}, { 업데이트연산자 : {바꿀데이터}} );
$set연산자: 지정한 필드의 값을 변경하거나, 해당 필드가 없는 경우 새로운 필드를 추가(덮어쓰기)$unset연산자: 특정 필드를 제거합니다. 지정된 필드가 문서에 존재한다면 그 필드가 삭제되며, 필드가 없다면 아무런 작용을 하지 않음.
deleteOne()메서드와의 차이 : 필드 레벨에서의 변경이 필요한 경우$unset을 사용하고, 전체 문서를 삭제하고자 하는 경우.deleteOne()을 사용$inc연산자: 기존 값이 숫자일 경우 숫자 증감 시 사용.
// app/edit/[id]/page.js
import EditForm from "@/components/EditForm";
import { connectToDatabase } from "@/utils/database";
import { ObjectId } from "mongodb";
export default async function EditPage({ params }) {
const { postCollection } = await connectToDatabase();
let data = await postCollection..findOne()({ _id: new ObjectId(params.id) });
const editData = { ...data, _id: data._id.toString() };
return <EditForm editData={editData} />;
}
<input type="hidden" name="_id"value={editData._id}/>
input type="hidden을 통해 UI에 노출시키지 않을 수 있다.router.refresh() : 이전과 바뀐점을 분석해서 바뀐부분만 새로고침 (soft refresh)// src/components/EditForm.js
"use client";
import styles from "./edit.module.css";
import { useRouter } from "next/navigation";
import { useEffect, useState } from "react";
export default function EditForm({ editData }) {
const [title, setTitle] = useState("");
const [content, setContent] = useState("");
const [message, setMessage] = useState("");
const router = useRouter();
useEffect(() => {
setTitle(editData.title);
setContent(editData.content);
}, []);
const handleChange = (e) => {
const { name, value } = e.target;
if (name === "title") {
setTitle(value);
} else if (name === "content") {
setContent(value);
}
};
const handleSubmit = async (e) => {
e.preventDefault();
const _id = e.target._id.value;
const title = e.target.title.value;
const content = e.target.content.value;
try {
const response = await fetch("/api/edit", {
method: "PATCH",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ _id, title, content }),
});
if (!response.ok) {
throw new Error("네트워크 응답이 올바르지 않습니다.");
}
setMessage("글이 수정되었습니다😊");
router.push("/list");
router.refresh();
} catch (error) {
console.error(error);
setMessage(error.message);
}
};
const handleCancel = () => {
router.push("/list");
};
return (
<div className={styles["flex-col"]}>
<h2>게시글 수정</h2>
{message && <p>{message}</p>}
<form
className={`${styles.form} ${styles["flex-col"]}`}
onSubmit={handleSubmit}
>
<input
type="hidden"
name="_id"
defaultValue={editData._id.toString()}
/>
<input
className={styles.input}
name="title"
placeholder="글제목"
value={title}
onChange={handleChange}
/>
<textarea
name="content"
cols="30"
rows="10"
value={content}
onChange={handleChange}
/>
<button type="button" onClick={handleCancel}>
취소
</button>
<button type="submit">수정</button>
</form>
</div>
);
}
// /app/api/edit/route.js
import { connectToDatabase } from "@/utils/database";
import { ObjectId } from "mongodb";
import { NextResponse } from "next/server";
export async function PATCH(req) {
try {
// 요청 본문에서 데이터 추출
const { title, content, _id } = await req.json();
const { postCollection } = await connectToDatabase();
const result = await postCollection.updateOne(
{ _id: new ObjectId(_id)}, // 업데이트할 게시글 식별
{ $set: { title, content } } // 업데이트할 내용
);
console.log(result);
return NextResponse.json({
message: "게시글이 성공적으로 수정되었습니다.",
});
} catch (error) {
console.error(error);
return NextResponse.json(
{ error: "서버 오류가 발생했습니다." },
{ status: 500 }
);
}
}
Warning: Only plain objects can be passed to Client Components from Server Components.
import EditForm from "@/components/EditForm";
import { connectToDatabase } from "@/utils/database";
import { ObjectId } from "mongodb";
export default async function EditPage({ params }) {
const { postCollection } = await connectToDatabase();
let editData = await postCollection.findOne({ _id: new ObjectId(params.id) });
/*
Warning: 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.
{_id: {buffer: ...}, title: "hi", content: ...} */
return <EditForm editData={editData} />;
}
클라이언트 컴포넌트에 plain object가 아닌 객체(예: ObjectId 객체)를 전달하려고 했기 때문에 발생
MongoDB에서 가져온 데이터를 클라이언트 컴포넌트로 전달하기 전에 _id 값을 문자열로 변환!
const editData = { ...data, _id: data._id.toString() };
_id 필드가 문자열이 되어 클라이언트 컴포넌트로 안전하게 전달될 수 있다.
import EditForm from "@/components/EditForm";
import { connectToDatabase } from "@/utils/database";
import { ObjectId } from "mongodb";
export default async function EditPage({ params }) {
const { postCollection } = await connectToDatabase();
let data = await postCollection.findOne({ _id: new ObjectId(params.id) });
// MongoDB에서 가져온 데이터를 클라이언트 컴포넌트로 전달하기 전에 _id 값을 문자열로 변환
const editData = { ...data, _id: data._id.toString() };
return <EditForm editData={editData} />;
}