hacca8

API Routesで設定するAPIにSWRでPOSTする(+ useRouterの使用)

Next.jsではAPI Routesを利用して簡単にAPIエンドポイントが設定できます。
今回はAPI Routesで設定するエンドポイントにuseSWRを使ってPOSTしてみます。

  • パッケージ
"next": "12.3.1",
"swr": "^1.3.0",

静的なページからPOSTする

/api/postに投稿する静的なページpost.jsを作成します。

  • src/pages/post.js
import useSWR from 'swr'

const Page = () => {
  const post = {
    method: 'POST',
    headers: { 'Content-Type': 'application/json'},
    body: JSON.stringify('postページからの投稿'),
  }
  const fetcher = (url) => fetch(url, post).then(r => r.json())
  const { data, error } = useSWR('/api/post', fetcher, { shouldRetryOnError: false })

  if (error) return <p>failed to load</p>
  if (!data) return <p>loading...</p>
  return <p>{data}</p>
}

export default Page

fetchを利用してPOSTしています。
今回は簡単に確認するため、bodyに固定のテキストを設定しています。通常はinputやtextareaのフォームからデータを設定するなどが多いと思います。
useSWRの第3引数にオプションを設定しています。shouldRetryOnErrorはフェッチでエラーが発生した場合にリトライするかのオプションです。falseですとリトライされません。

  • src/pages/api/post.js
const handler = async(req, res) => {
  const data = req.body
  res.status(200).json(`/api/postで「${data}」を受け取りました`)
}

export default handler

今回はPOSTできているか確認するため、受け取ったデータを含めたテキストを返しています。通常はここからDBを操作して結果を返すなどが多いと思います。
req.bodyでPOSTのbodyが読み取れます。

以上で/postにアクセスすると、/api/postで「postページからの投稿」を受け取りましたと表示されます。

動的なページからPOSTする

Dynamic Routesを利用して、動的なページからPOSTできるか確認します。
API(src/pages/api/post.js)は静的なページと同じものを利用します。

  • src/pages/[slug].js
import { useRouter } from 'next/router'
import useSWR from 'swr'

const Page = () => {
  const { slug } = useRouter().query
  const post = {
    method: 'POST',
    headers: { 'Content-Type': 'application/json'},
    body: JSON.stringify(`${slug}ページからの投稿`),
  }
  const fetcher = (url) => fetch(url, post).then(r => r.json())
  const { data, error } = useSWR(slug ? '/api/post' : null, fetcher, { shouldRetryOnError: false })

  if (error) return <p>failed to load</p>
  if (!data) return <p>loading...</p>
  return <p>{data}</p>
}

export default Page

useRouterを利用してslug(query)を読み取ります。この状態で/slug01にアクセスすると/api/postで「slug01ページからの投稿」を受け取りましたと表示されます。
useSWRの第1引数にslugを渡しますが、useRouter().queryは初回にundefinedが返るため、そのままuseSWRを利用するとエラーになります。
そのためslugがundefinedの場合はnullとしてリクエストが開始されないようにしています。

参考: SWR 条件付きフェッチ

Readだけでしたら動的なAPI Routesが楽な場合が多いですが、POSTが必要でしたら上記のようにエンドポイント側は固定にする方が簡潔な場合もあります。