microCMS

Next.jsでカテゴリー機能を実装してみよう

かみむら

この記事は公開後、1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

本記事ではNext.jsでカテゴリー機能を実装していきます。以前に書いたmicroCMS + Next.jsでJamstackブログを作ってみようの拡張版になります。本記事はこのチュートリアルを終えてる前提で話を進めていきます。

今回の作成イメージはmicroCMSブログのサイドバーにあるカテゴリーの一覧です。各カテゴリーにブログ記事が1対多の関係で紐付いています。例として、エンジニアリングをクリックすると、そこに紐付いた複数のブログ記事を取得することができます。

前提

下記のバージョンで開発を行っています。バージョンの差異によって若干機能が異なる可能性があります。

  • Next 13.1.1
  • react 18.2.0
  • react-dom 18.2.0


一覧ページでカテゴリーを表示

入稿したカテゴリーコンテンツのデータを一覧ページで取得して表示してみましょう。pages/index.jsにロジックを書いていきます。一覧ページの実装はmicroCMS + Next.jsでJamstackブログを作ってみようを参考にしています。こちらはコードの全体像です。

// pages/index.js
import Link from "next/link";
import { client } from "../libs/client";

export default function Home({ blog, category }) {
  return (
    <div>
      <ul>
        {category.map((category) => (
          <li key={category.id}>
            <Link href={`/category/${category.id}`}>{category.name}</Link>
          </li>
        ))}
      </ul>
      <ul>
        {blog.map((blog) => (
          <li key={blog.id}>
            <Link href={`/blog/${blog.id}`}>{blog.title}</Link>
          </li>
        ))}
      </ul>
    </div>
  );
}

// データをテンプレートに受け渡す部分の処理を記述します
export const getStaticProps = async () => {
  const data = await client.get({ endpoint: "blog" });
  // カテゴリーコンテンツの取得
  const categoryData = await client.get({ endpoint: "categories" });

  return {
    props: {
      blog: data.contents,
      category: categoryData.contents,
    },
  };
};

ポイントはendpointにcategories を指定して、カテゴリーコンテンツを取得していることです。categoryData.contentsが配列で、これをcategoryとしてpropsに渡してあげます。あとは、ブログコンテンツと同じで配列データに対してmapしてブラウザ上に表示します。

カテゴリーコンテンツが上手く取得できているか確認しましょう。

各カテゴリーページでブログコンテンツをフィルタリングする

一覧ページにカテゴリーコンテンツを表示することができました。次のステップとして、各カテゴリーページでブログコンテンツをフィルタリングしてみましょう。pages/category/[id].jsを作成します。コードの全体像はこちらです。

// pages/category/[id].js
import Link from "next/link";
import { client } from "../../libs/client";

export default function CategoryId({ blog }) {
  // カテゴリーに紐付いたコンテンツがない場合に表示
  if (blog.length === 0) {
    return <div>ブログコンテンツがありません</div>;
  }
  return (
    <div>
      <ul>
        {blog.map((blog) => (
          <li key={blog.id}>
            <Link href={`/blog/${blog.id}`}>{blog.title}</Link>
          </li>
        ))}
      </ul>
    </div>
  );
}

// 静的生成のためのパスを指定します
export const getStaticPaths = async () => {
  const data = await client.get({ endpoint: "categories" });

  const paths = data.contents.map((content) => `/category/${content.id}`);
  return { paths, fallback: false };
};

// データをテンプレートに受け渡す部分の処理を記述します
export const getStaticProps = async (context) => {
  const id = context.params.id;
  const data = await client.get({ endpoint: "blog", queries: { filters: `category[equals]${id}` } });

  return {
    props: {
      blog: data.contents,
    },
  };
};

filtersパラメータを使ってフィルタリングをします。今回のケースのように、単数のコンテンツ参照で使用できるのは [equals]のみです。content_idを指定することで紐付いたコンテンツを取得することができます。

client.get({ endpoint: "blog", queries: { filters: `category[equals]content_id` } });


ブラウザで確認すると、各カテゴリーに紐付いたブログコンテンツを取得することができます。

発展:タグ機能の考え方

チュートリアルを通じてカテゴリー機能が実装できました。今回の考え方はタグ機能の実装にも応用できます。microCMSブログのサイドバーにあるタグ機能を例としてみましょう。

カテゴリーコンテンツと同じようなAPIを作成します。ただし、同名のエンドポイントは使えないのでtagsとします。そして、ブログのAPIスキーマでtagsフィールドを追加して、複数コンテンツ参照としてタグを選択しましょう。

タグコンテンツとブログコンテンツが紐づく複数のコンテンツ参照では、[contains]を使用することでフィルタリングすることができます。ぜひ試しに実装してみてください。

client.get({ endpoint: "blog", queries: { filters: `tags[contains]content_id` } });

おわりに

今回はNext.jsでカテゴリーページの実装について解説しました。カテゴリー機能はブログやメディア作成では必須の機能になってきます。今回の記事が役立てば嬉しいです。


-----

microCMSは日々改善を進めています。
ご意見・ご要望は管理画面右下のチャット、公式Twitterメールからお気軽にご連絡ください!
引き続きmicroCMSをよろしくお願いいたします!

まずは、無料で試してみましょう。

APIベースの日本製ヘッドレスCMS「microCMS」を使えば、 ものの数分でAPIの作成ができます。

microCMSを無料で始める

microCMSについてお問い合わせ

初期費用無料・14日間の無料トライアル付き。ご不明な点はお気軽にお問い合わせください。

お問い合わせ

microCMS公式アカウント

microCMSは各公式アカウントで最新情報をお届けしています。
フォローよろしくお願いします。

  • X
  • Discord
  • github

ABOUT ME

かみむら
フロントエンドエンジニア。テックブロガーでもあります。JAMstackアーキテクチャーやSPA(React、Vue)技術が好きです。