monaka

Next.jsで関連記事(レコメンド)を作る

Next.jsで作成したブログに関連記事(レコメンド)機能を追加した際の備忘録。自分の理解不足もあり実装するのにかなり苦労した。もし他にも苦戦している方がいれば参考になると嬉しい。

完成イメージ

参考にした記事

microCMSブログのmicroCMSで関連記事のレコメンド機能を実装してみよう を参考にした。今回自分が採用したのはリンク先の記事の2つ目のパターン(同じカテゴリの記事をレコメンドするもの)

レコメンドコンポーネントを作成する

「_compornents」配下に「Recommend」ディレクトリを作成し、その中に「index.tsx」と「index.module.css」を作成する

import type { News } from "@/app/_libs/microcms";
import Image from "next/image";
import Link from "next/link";
import styles from "./index.module.css";
import Date from "@/app/_components/Date";
import { RECOMMEND_LIST_LIMIT } from "@/app/_constants/";

type Props = {
  contents: News[];
  title: string;
};

export default function Recommend({ contents, title }: Props) {
  if (!contents || contents.length === 0) {
    return <div>記事がありません</div>;
  }

  const limitedContents = contents.slice(0, RECOMMEND_LIST_LIMIT);

  return (
    <section className={styles.recommendContainer}>
      <div className={styles.cardContainer}>
        <div className={styles.recommendItems}>
          {limitedContents.map((item) => (
            <div key={item.id} className={styles.recommendItem}>
              <Link href={`/blog/${item.id}`} className={styles.recommendLink}>
                <Image
                  src={item.thumbnail?.url || "/no-image.png"}
                  alt={item.title}
                  width={1200}
                  height={630}
                  className={styles.thumbnail}
                  priority
                />
                <div className={styles.titleContainer}>
                  <h4 className={styles.titleText}>{item.title}</h4>
                  {item.publishedAt && <Date date={item.publishedAt} />}
                </div>
              </Link>
            </div>
          ))}
        </div>
      </div>
    </section>
  );
}

続いてindex.module.cssは以下のようにした。(これもmicroCMSブログのデザインを踏襲した。できる限り寄せている)

.recommendContainer {
  display: grid;
  gap: 1rem; 
}

.cardContainer {
  border-radius: 0.5rem; 
  background-color: white; 
}

.recommendItems {
  display: grid;
  gap: 1rem; 
}

.recommendItem {
  display: block; 
}

.recommendLink {
  display: block; 
}

.thumbnail {
  width: 100%; 
  height: auto; 
  border-radius: 0.5rem; 
  object-fit: cover; 
}

.title {
  margin-bottom: 1.5rem; 
  font-size: 1.25rem; 
  font-weight: 600; 
}

.titleContainer {
  display: block; 
}

.titleText {
  font-size: 18px; 
  transition: color 0.3s; 
}

@media (min-width: 768px) {
  .recommendItems {
    grid-template-columns: repeat(2, 1fr); 
  }
}

@media (max-width: 767px) {
  .recommendItems {
    grid-template-columns: 1fr; 
  }
}

Dateコンポーネントから参照する

今回、レコメンドの記事の日付も表示させたかった。microCMSテンプレートで作成したものなら、Dateコンポーネントがあるはずなので、そこからimportして表示している

レコメンドの表示件数を制御する

レコメンド表示件数はmicroCMSのデフォルトの設定だとおそらく10件表示されるはず。少し多いので今回は4件ほどにしたい。先ほどのコードには記載済みだが、「RECOMMEND_LIST_LIMIT」というもので、表示件数を出し分けしている。

「_constants」ディレクトリの中にある、index.tsに以下のように追記した

export const MEMBERS_LIST_LIMIT = 100;
export const TOP_NEWS_LIMIT = 10;
export const NEWS_LIST_LIMIT = 10;
export const RECOMMEND_LIST_LIMIT = 4;

あとから表示件数を変更したくなった場合はこの4のところを6とか、8とかに変更する。今回CSSでPCは2カラム、スマホは1カラムにしている。2の倍数の数字が良いだろう

GetBlogsByCategoryParams関数を追加する(つまづきポイント)

後から考えれば簡単だったが、つまづいてしまったときに、気づくことができなかった。「_libs」ディレクトリのmicrocms.tsに以下を追加した。ざくっというと、レコメンドで表示する記事を取得するための関数をここで定義している。

type GetBlogsByCategoryParams = {
  limit: number;
  filters?: string;
};

export const getBlogsByCategory = async ({
  limit,
  filters,
}: GetBlogsByCategoryParams) => {
  const response = await client.get({
    endpoint: "news",
    queries: {
      limit: limit,
      filters: filters,
    },
  });

  return response;
};

まとめ

最終的にイメージしていたものを作成することができたが、かなり苦労してしまった。だが、触っている中で何となく動きが理解できてきたので、次も機能追加を頑張りたい

Next.js+ヘッドレスCMSではじめる! かんたんモダンWebサイト制作入門 高速で、安全で、運用しやすいサイトのつくりかた
Next.js+ヘッドレスCMSではじめる! かんたんモダンWebサイト制作入門 高速で、安全で、運用しやすいサイトのつくりかた
Amazon楽天市場Yahoo!ショッピング

関連記事