web

Next.js + microCMSでカテゴリ一覧ページを作る

公開日:2021年11月20日
最終更新日:2021年11月26日

以前は記事にカテゴリ名を表示だけはしていたのですが、ページネーションを実装したついでに、カテゴリ一覧も追加しました。
ただ、調べてもなかなか実装方法でてこなかったので、備忘録でまとめておきます。

仕様

以下のように作ります

  • カテゴリ別に一覧ページを作る
  • 各カテゴリ別にページングを作る
  • パスの例 example.com/blog/web/page/1


そもそもセレクトフィールドが間違いだった

記事に表示のためにセレクトフィールドをスキーマに持たせていて、カテゴリの表示だけはしていました。
https://blog.microcms.io/add-select-field/

当初は記事にカテゴリ持たせといて、filterかけて取得したら一覧作れるのかなと思ってたけど違ったみたいです。早めに気づいて良かった。

実際は、microCMSのヘルプに書かれてるように、カテゴリのためのコンテンツ(API)を作り、カテゴリを付けたいコンテンツの方で「コンテンツ参照」のスキーマを作る必要があります。
http://help.microcms.io/ja/knowledge/categories-and-tabs

ブログの記事にカテゴリの表示だけなら当初の方法でいいのですが、カテゴリ一覧メニューや、カテゴリ別ページを作るためにはカテゴリだけを取得できるAPIが必要です。タグのような複数選択の場合は「コンテンツ複数参照」でスキーマを作ります。

ブログを作る場合のスキーマは、microCMSが自社ブログのソースコードをGitHubに上げてくれてるので、Readmeに書いてあるスキーマを参考にするのがいいです。
https://github.com/microcmsio/microcms-blog

Pages

pages以下blogのところを抜き出すとこのような構成にしています。細かいとこはやりやすいようにしてください。

├── pages
│   ├── blog
│   │   ├── [category]
│   │   │   ├── [id]
│   │   │   │   └── index.tsx // ブログ個別ページ
│   │   │   └── page
│   │   │       └── [id]
│   │   │           └── index.tsx // カテゴリの一覧ページ
│   │   ├── index.tsx // ブログトップ(blog/page/1と表示は同じ)
│   │   └── page
│   │       └── [id]
│   │           └── index.tsx // ブログ一覧(pagination用。blog/page/[ページ数])


実装のポイント

全部書くとしんどいので、ポイントになるとこだけピックアップ。全体はGitHubのリポジトリ見てください。
https://github.com/mismith0227/mismith.me

getStaticPathsでパスを生成するのですが、記事全体のページング作る実装に加えて、まずはカテゴリを取得して、その分をmapする必要があります。

export const getAllCategoryPagePaths = async () => {
  const resCategory = await client.get({
    endpoint: 'blog-category',
  })

  const paths: string[] = await Promise.all(
    resCategory.contents.map((item: BlogCategory) => {
      const result = client
        .get({
          endpoint: 'blog',
          queries: {
            filters: `category[equals]${item.id}`,
          },
        })
        .then(({ totalCount }) => {
          const range = (start: number, end: number) =>
            [...Array(end - start + 1)].map((_, i) => start + i)

          return range(1, Math.ceil(totalCount / BLOG_PER_PAGE)).map(
            (repo) => `/blog/${item.id}/page/${repo}`
          )
        })
      return result
    })
  )


  return paths.flat()
}


export const getStaticPaths: GetStaticPaths = async () => {
  const paths = await getAllCategoryPagePaths()

  return { paths, fallback: false }
}


ポイントとしてはこれが全てなんですが、冒頭でも書いた通り当初は記事のAPIの中でセレクトフィールドでカテゴリを付けていたため、getStaticPathsでどうやってカテゴリ情報とればいいのか悩んでました。
コンテンツ参照の存在を知って、実装することができました。

さいごに

今まで最低限の機能しか持たせてなかったですが、カテゴリとか一般的なブログの機能を実装しようとするとまだまだ知らないこと多いです。
今後もNext.jsの知見貯めたいので、もっと一般的なブログに近い実装を追加していきたいです。

About the author

大阪でフロントエンドエンジニアをしています。写真を撮るのが趣味です。よかったら500pxに載せてる写真も見てください。
web上に公開しているので、正確さに可能な限り努力してますが、個人の備忘録程度に書いてるので、ご自身の判断で参考程度に読んでください。
間違いやご意見があれば、コンタクトやSNSに気軽にご連絡ください。

Read next

Category

  • web
  • 雑記