티스토리 뷰

어떻게 해야할까?
- Page가 필요하겠네? 여러 input들을 받을 수 있는...
- API도 필요하겠네? file에 저장할 input을 전달받을...
- 서버에서 실제로 파일을 저장할 writePost 함수도 필요하겠네?
- 작성이 성공하면 해당 page로 가는 Link도 제공하면 좋겠군...
우선 필요한 파일들을 생성해 봅시다
- pages/post/write.js Page 추가
- pages/api/post/write.js API 추가
- lib/posts.js 안에 writePost 함수 추가
먼저 글을 쓸 수 있는 페이지를 구성해 봅시다
글을 쓸 수 있는 form이 있는 페이지를 만들어보겠습니다.
📜 pages/post/write.js
import { useRef } from 'react'
import Layout from '../../components/Layout'
export default function Write() {
const idRef = useRef(undefined)
const titleRef = useRef(undefined)
const contentRef = useRef(undefined)
const handleSubmit = (event) => {
event.preventDefault()
}
return (
<Layout>
<h1>Write a post</h1>
<form onSubmit={handleSubmit}>
<input type="text" name="id" placeholder="id" required ref={idRef} />
<br />
<input
type="text"
name="title"
placeholder="title"
required
ref={titleRef}
/>
<br />
<textarea
type="text"
name="content"
placeholder="content"
required
ref={contentRef}
/>
<br />
<input type="submit" value="Create" />
</form>
</Layout>
)
}
우선 위와 같이 간단한 ref 연결과 submit 함수 틀만 선언해 두었습니다.
그 다음으로, 기존 post + 새 post를 합치는 기능 함수를 만들어 봅시다
📜 lib/posts.js
export async function createPost({ id, title, date, content }) {
const fullPath = path.join(postsDirectory, `${id}.md`)
const data = `---
title: '${title}'
date: '${date}'
---
${content}`
fs.writeFileSync(fullPath, data)
}
그 다음은, 요청을 보낼 API Routes를 구성해 봅시다
우리는 지금 만든 API Routes에 id와 title과 content를 보내서 Server는 기존 글 + 새로운 글을 합치는 역할을 수행해야 한다는 점을 집중해봅시다.
📜 pages/api/post/write.js
import { createPost } from '../../../lib/posts'
import { format } from 'date-fns'
export default async function handler(req, res) {
const { id, title, content } = req.body
try {
await createPost({
id,
title,
date: format(new Date(), 'yyyy-MM-dd'),
content,
})
res.status(200).json({ message: 'create success' })
} catch (error) {
res.status(500).json({ error: `create failed ${error}` })
}
}
req.body에서 id와 title과 content를 가져와서, 좀 전에 만든 createPost로 요청을 보냈을 때 성공/실패 response 로직을 작성해줍니다.
이제 다시 form의 submit 함수로 돌아옵시다
📜 pages/post/write.js
const handleSubmit = (event) => {
event.preventDefault()
const id = idRef.current.value
const title = titleRef.current.value
const content = contentRef.current.value
if (id && title && content) {
fetch('/api/post/write', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
id,
title,
content,
}),
})
.then((response) => {
if (response.ok) {
return response.json()
}
throw new Error('Fetch Error')
})
.then((data) => alert(data.message))
.catch((error) => alert(`request error: ${error}`))
}
}
간단하게 유효성 검사를 해주고 모든 내용이 존재한다면 fetch를 보낸다는 내용이 포함되어 있습니다.
then/catch 부분을 보면, 성공 응답이 왔을 때만 response를 json으로 바꾸고 그 이외에는 error를 throw하고 있습니다. 그렇다면 아래에 있는 catch에서 에러를 잡아 alert를 띄울 것입니다.


파일이 잘 생성된 것을 확인할 수 있습니다.
Create한 후에 Link를 보여줘서 작성된 Post로 이동하는 것도 해봅시다
먼저 Link 태그를 보여줄지 보여주지 말지를 경우에 따라 렌더링하기 위해 boolean타입의 state를 하나 선언해줍니다.
📜 pages/post/write.js
const [showLink, setShowLink] = useState(false)
그 후 form 바로 아래에 showLink가 true일 때만 보여줄 Link 태그도 추가해줍니다.
<form>
</form>
{showLink && (
<Link href={`/post/${idRef.current.value}`}>Created Post</Link>
)}
이때 showLink는 response가 성공적일 때 업데이트해주도록 코드를 추가합니다.
const handleSubmit = (event) => {
event.preventDefault()
const id = idRef.current.value
const title = titleRef.current.value
const content = contentRef.current.value
if (id && title && content) {
fetch('/api/post/write', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
id,
title,
content,
}),
})
.then((response) => {
if (response.ok) {
return response.json()
}
throw new Error('Fetch Error')
})
.then((data) => {
setShowLink(true) ******
alert(data.message)
})
.catch((error) => alert(`request error: ${error}`))
}
}

이번 글에서는 write 페이지를 만들고 API Route까지 해서 새로운 글을 쓸 수 있도록 해보았습니다 :)
1. API Routes
요청하는 코드는 Client Side에만 두자
2. POST 요청
Post를 직접 write하고 POST 해봄
'프론트엔드 > Next.js' 카테고리의 다른 글
[Next.js] ../ 때문에 길어지는 import문은 별칭 절대경로 @ 사용하기 (0) | 2023.06.27 |
---|---|
[Next.js] Dynamic Import(Lazy load) & Hydration & Static Export (0) | 2023.06.27 |
[Next.js] SSG를 활용해서 다이나믹한 page 생성 with getStaticPaths, fallback 에러 해결 (0) | 2023.06.25 |
[Next.js] SSG 선택 기준과 SSG를 하는 두 가지 방법(with data, without data) (0) | 2023.06.23 |
[Next.js] Layout과 Styling - Image 컴포넌트, Head 컴포넌트, Global CSS (0) | 2023.06.23 |
- Total
- Today
- Yesterday
- 프론트엔드 공부
- testing
- 디프만
- 인프런
- react
- 프로젝트 회고
- CSS
- Python
- 파이썬
- 프론트엔드
- next.js
- rtl
- 리액트 훅
- 리액트
- 딥러닝
- styled-components
- JSP
- react-query
- 자바
- frontend
- 타입스크립트
- 프론트엔드 기초
- 데이터분석
- HTML
- TypeScript
- 스타일 컴포넌트 styled-components
- 자바스크립트
- 자바스크립트 기초
- 머신러닝
- jest
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |