<Link href={`/edit/${item._id}`}>수정✏️</Link>
게시판 리스트에서 수정 버튼을 링크로 만들어준다.
/edit/${item._id} 는 게시물의 아이디를 페이지 주소로 보내준다는것 / 라우터 페이지 주소로 생성
라우터 [] 방법으로 수정페이지를 하나 만들어준다.
import { connectDB } from '@/util/database';
import { ObjectId } from 'mongodb';
const page = async(props:any) => {
let result = await (await connectDB).db("forum").collection('post').findOne({_id:new ObjectId(props.params.id)}) // 여기 id 는 [라우터 제목]
console.log(result, "여기")
//위는 게시글 데이터를 가져와서 input 에 뿌려주기 위해서 가져옴
return (
<div className='p-20'>
<h4>글수정 페이지</h4>
<form action="/api/post/new" method="POST">
<input name="title" placeholder='제목' defaultValue={result.title}></input>
<input name="content" placeholder='내용' defaultValue={result.content}></input>
<button type="submit">Post 버튼</button>
</form>
</div>
);
};
export default page;
데이터를 불러와서 인풋에 넣고싶으면 인풋 가운데 {} 이거롤 넣는게 아니라 value= {이안에 넣는것이다.}
value 가 안될경우 defaultValue={이걸 사용해도 된다 용도는 같음} 넥스트에서는 디폴트벨류를 쓰는게 더잘들어갈때가 있다.
차이. value 는 수정이 안되고 고정이된다. 아무래도 벨류 자체 그렇기때문
defaultValue 는 수정이 가능. 처음상태만 디폴트 값으로 넣어주기 때문인듯.
수정하는방법 위 코드사이에
await (await connectDB).db("forum").collection('post').updateOne({수정할 게시물정보},
{$set:{title:'바보',content:'바보2'}}
)
넣어주면된다. set는 수정할 항목이다. 위에는 예시다.
바로위에것을 api 폴더안에 포스트 폴더안에 edit.tsx 파일을 만들어서 그안에서 작성한다
Tip. edit 폴더에서 요청.body 를 콘솔로 출력하면 인풋에 수정한걸 요청.body 로 받는다.
참고로 요청.body 자체가 오브젝트 스코프 자료형 이기때문에 따로 위처럼 title / content 나눠서 안해줘도된다. 포괄적으로 수정한다.
전체 코드 완성
psge.tsx [라우터 페이지다.]
import { connectDB } from '@/util/database';
import { ObjectId } from 'mongodb';
const page = async(props:any) => {
let result = await (await connectDB).db("forum").collection('post').findOne({_id:new ObjectId(props.params.id)}) // 여기 id 는 [라우터 제목]
console.log(result, "여기")
return (
<div className='p-20'>
<h4>글수정 페이지</h4>
<form action="/api/post/edit" method="POST">
<input name="title" placeholder='제목' defaultValue={result.title}/>
<input name="content" placeholder='내용' defaultValue={result.content}/>
<input style={{display:'none'}} name="_id" defaultValue={result._id.toString()}></input>
<button type="submit">전송버튼 버튼</button>
</form>
</div>
);
};
export default page;
위코드 설명 input 중에 display:'none' 건 api edit.tsx 에 _id 값을 => 요청.body 넣기위해서 input 에 넣어서 보낸것이다.
개인적인 의견은 그냥 수정안되게 인풋설정해서 보여도 상관없지 않을까?
api 폴더의 edit.tsx
import { connectDB } from '@/util/database';
import { ObjectId } from 'mongodb';
const edit = async(요청:any,응답:any) => {
if (요청.method == 'POST'){
const 바꿀거 = {
title:요청.body.title,
content:요청.body.content
} // 위는 바꿀데이터 골라서 변수에 넣어주기 $set 에 들어간다.
await (await connectDB).db("forum").collection('post').updateOne({_id: new ObjectId(요청.body._id)},
{$set:바꿀거}
)
응답.status(200).redirect(302,'/list')
// 위는 전부 처리 완료후 할행동을 넣은것이다 302가 들어가야 작동할때도 있고 안들어가도 될때가있다.
}
};
export default edit;
바꿀거를 만든이유는 위에서도 말했지만.
요청.body 필요한 데이터 말고 아이디값도 있어서 따로 빼줘서 넣은것이다.
updateOne는 업데이트 덮어쓰기할 데이터 id 값이나 위치값을 넣어주면된다.
new ObjectId 를 쓴이유는 아이디값 데이터 구조가 저렇기때문
{
_id: new ObjectId("6488715e894603854694cb12"),
title: '수정했다 1',
content: '수정했다 2'
}
저게없다면 그냥 코드만 요청.body._id 만 넣으면되었다.
중요
$set: 바꿀꺼
$set 가 데이터 에 덮어씌울 새로운 데이터 이다.
그래서 요청.body 로 인풋에 새롲거은걸 받아서 $set 안에 넣어주면 새로운 데이터로 덮어싀워준다.
그외에 $inc:1
같은경우는 조회수에 쓰일때쓰는거같다 숫자를 증감시켜주는 기능.
서버기능 만들기
서버에 DB수정하는 기능 만들고
유저가 버튼누르면 그걸 실행하라고 부탁하는 식으로 코드짜면 됩니다.
<div className="write">
<form action="/api/post/edit" method="POST">
<input name="title" defaultValue={result.title}/>
<input name="content" defaultValue={result.content}/>
<button type="submit">전송</button>
</form>
</div>
action 속성에 이렇게 적으면 /api/post/edit.js 파일 안에 있는 코드가 실행되니까
그 파일 만들어서 기능만들면 되겠군요.
그래서 서버기능 만들러 api 폴더로 이동해봅시다.
import { connectDB } from "@/util/database"
import { ObjectId } from "mongodb";
export default async function handler(요청, 응답) {
if (요청.method == 'POST'){
console.log(요청.body)
let db = (await connectDB).db('forum')
let result = await db.collection('post').updateOne({게시물정보}, { $set : {바꿀데이터}} );
응답.redirect(302, '/list')
}
}
pages/api/post/edit.js 파일 만들고 이렇게 코드를 짰습니다.
유저가 폼으로 보낸 데이터는 요청.body 출력하면 있으니까 거기서
바꿀데이터와 게시물정보도 꺼내서 저기에 잘 채워넣으면 될 것 같은데
하지만 요청.body 출력해보면 유저로부터 전달되는 데이터가 {title : 어쩌구, body : 어쩌구} 밖에 없습니다.
바꿀데이터는 있는데 게시물정보는 없는데유
<div className="write">
<form action="/api/post/edit" method="POST">
<input name="title" defaultValue={result.title}/>
<input name="content" defaultValue={result.content}/>
<input name="_id" defaultValue={result._id.toString()}/>
<button type="submit">전송</button>
</form>
</div>
그럼 유저에게 보내라고 하면 되는거 아니겠습니까.
서버에서 코드짜다가 데이터같은게 없으면 유저에게 보내라고 하거나 DB에서 꺼내보면 됩니다.
수정페이지에 <input>을 하나 더 만들고 _id를 집어넣어둡니다.
그럼 서버로 _id 이름으로 ObjectId('어쩌구') 에서 '어쩌구' 내용부분만 전달됩니다.
Q. 왜 .toString() 쓰냐고요?
서버와 데이터 주고받을 때 문자, 숫자, JSON 이런 것만 주고받을 수 있습니다.
저런 이상한 데이터들은 문자로 치환하는 방법을 찾아서 쓰면 되겠습니다.
Q. _id 같은건 유저에게 안보여주는게 좋지않나요?
넴 display : none 같은 스타일 줘서 숨기면 됩니다.
import { connectDB } from "@/util/database.js"
import { ObjectId } from "mongodb";
export default async function handler(요청, 응답) {
if (요청.method == 'POST'){
let 바꿀거 = {title : 요청.body.title, content : 요청.body.content}
let db = (await connectDB).db('forum')
let result = await db.collection('post').updateOne(
{_id : new ObjectId(요청.body._id)},
{ $set : 바꿀거}
);
console.log(result)
응답.redirect(302, '/list')
}
}
1. 요청.body에서 이것저것 꺼내서 바꿀데이터를 만들어서 updateOne() 안에 집어넣었습니다.
2. 요청.body._id 꺼내서 게시물정보를 만들어서 updateOne() 안에 집어넣었습니다.
{ } 자료같은게 어렵고 어색하면 자바스크립트 기초강의 들을 시점입니다.
(참고) 실은 GET, POST 말고도 PUT, DELETE 요청으로 서버와 통신할 수도 있습니다.
PUT은 수정, DELETE는 삭제할 때 쓰면 좋은데 서버 api들 끼리 이쁘게 구분하기 위함이고 필수는 아닙니다.
단점은 <form>으로 데이터 전송시 PUT, DELETE는 사용할 수 없어서 굳이 쓰고 싶으면 외부 라이브러리 설치하거나 해야합니다.
그래서 코드가 너무 길거나 그런게 아니면 <form>으로 데이터 전송시엔 일단 POST 요청 쓰는게 낫습니다.
오늘의 결론은
- document 수정하려면 updateOne 쓰면 됩니다. 값 변경말고 증가/감소도 가능함
- 서버에서 코드짜다가 필요한 데이터가 없으면 1. 유저에게 보내라고 하거나 2. DB에서 꺼내써도 됩니다.
'Next' 카테고리의 다른 글
next13 게시판 삭제기능 만들어보기 2 (0) | 2023.06.16 |
---|---|
next13 게시판 삭제기능 만들어보기 1 (0) | 2023.06.15 |
next13 게시판 글 작성기능 만들기 2 (1) | 2023.06.13 |
next.13 게시판 글 작성기능 만들기 (0) | 2023.06.07 |
next.13 몽고db 글목록 조회기능/ 다이나믹 라우터 사용법 / 캐치 url (0) | 2023.06.02 |