フリーランスWebエンジニア HTNCode

▲
  • HOME
  • ABOUT
  • SERVICE
  • ACHIEVEMENT
  • BLOG
  • CONTACT
  • githubIcon
  • twitterIcon
プライバシーポリシー
footerLogoImage

© HTNCode All Rights Reserved.

eyecatch

ブログにページネーションを実装してみた

作成日時:2023年8月18日 00:48

更新日時:2023年8月18日 02:10

Next.js

microCMS

Tutorial

はじめに

HTNCodeです。

ブログの記事数が徐々に増えてきたので、ページネーションを実装してみました。

今日はその解説をしようと思います。

 

以下は、参考にさせていただいたブログ記事です(実装はNext.js13.4.9なので若干記述を変えてます)。

■【microCMS】Next.js(SSG)でページネーションを実装してみよう

https://blog.microcms.io/next-pagination/

 

前提

以下の環境で実装しました。

・Next.js 13.4.9

・react 18.2.14

・react-dom 18.2.6

 

実装の流れ

実装の流れは以下の3ステップです。

1.appディレクトリ配下にcomponentsフォルダを作成し、ページネーション用のBlogPaginationコンポーネントファイルを作成

2.同じくappディレクトリ配下にあるblogフォルダ内のpage.tsx(ブログ一覧ページ)内に、BlogPaginationコンポーネントを追加

3./blog/page/1や/blog/page/2という感じでページネーションごとのページを作成するため、blogフォルダ内にpage/[id]/page.tsxファイルを作成

 

1.BlogPaginationコンポーネントファイルの作成

componentsフォルダを作成し、その中にBlogPagination.tsxファイルを作成、以下を記述します。

import Link from "next/link";
import { FC } from "react";
import styles from "@/app/styles/BlogPagenation.module.css"; //CSSはお好みで

interface BlogPaginationProps {
  totalCount: number;
}

export const BlogPagination: FC<BlogPaginationProps> = ({ totalCount }) => {
  const PER_PAGE = 6; // 6記事ずつ

  //配列を作成
  const range = (start: number, end: number) => {
    const length = end - start + 1;
    return length > 0 ? [...Array(length)].map((_, i) => start + i) : [];
  };

  return (
    <div className={styles.BlogPagenation}>
      <ul>
        {/* 作成した配列をPER_PAGE(6)で割る(例えば12記事あるなら÷6でページネーションのリスト数として2が返る) */}
        {range(1, Math.ceil(totalCount / PER_PAGE)).map((number, index) => (
          <li key={index}>
            <Link href={`/blog/page/${number}`}>{number}</Link>
          </li>
        ))}
      </ul>
    </div>
  );
};

 

rangeで配列を作成し、それをPER_PAGEで設定した1ページあたりの記事数で割ったものをmap関数で展開、

その際に、Linkタグで`/blog/page/${number}`として、展開されたページネーションのページ数に応じたパスを設定しています。

 

BlogPagenationコンポーネントを組み込む

作成したBlogPagenationコンポーネントをブログ一覧用のコンポーネントに組み込みます。

※不要な部分は省略しています

import { BlogPagination } from "@/app/components/BlogPagination";

//microCMSのブログデータ取得
async function getBlogPosts() {
  const postsResponse = await client.get({
    customRequestInit: {
      cache: "no-store", // キャッシュを利用せずに常に新しいデータを取得
    },
    endpoint: "blog",
    queries: {
      offset: 0, //offsetを0とする
      limit: 6, //6記事ずつ
      fields: "id,title,content,eyecatch,category,createdAt,updatedAt", // 取得するフィールドを指定
    },
  });

  const totalCount = postsResponse.totalCount;
  const posts = postsResponse.contents;
  return { posts, totalCount }; //オブジェクトとして返す
}

export default async function Blog() {
 let { posts, totalCount }: any = await getBlogPosts(); //オブジェクトを分解して posts と totalCount の両方を取得

 return (
    <>
    ...ブログ記事の展開記述...

      <BlogPagination totalCount={totalCount} />
    </>
  );
}

 

<BlogPagination totalCount={totalCount} />とすることで、totalCountが60(60記事)なら1~10のページネーションが作成されます。

 

ページネーションごとのページを作成

blogフォルダ内にpageフォルダを作成し、その中にさらに[id]フォルダを作成、その中にpage.tsxを作成し、以下を記述します。

※不要な部分は省略しています

import Link from "next/link";
import { BlogPagination } from "@/app/components/BlogPagination";
import { client } from "@/app/libs/client";
import styles from "@/app/blog/page.module.css";  //CSSはお好みで
import "@/app/styles/globals.css";  //CSSはお好みで

const PER_PAGE = 6; // 6記事ずつ

async function getBlogPosts(params: any) {
  const id = params.id;
  const offset = (id - 1) * 6; //ポイント

  const postsResponse = await client.get({
    customRequestInit: {
      cache: "no-store",
    },
    endpoint: "blog",
    queries: {
      offset: offset,
      limit: 6, //6記事ずつ
      fields: "id,title,content,eyecatch,category,createdAt",
    },
  });
  const totalCount = postsResponse.totalCount;
  const posts = postsResponse.contents;
  return { posts, totalCount };
}

export default async function BlogPageId({ params }: any) {
  let { posts, totalCount }: any = await getBlogPosts(params);

  return (
   <>
    ...ブログ記事の展開記述...

    <BlogPagination totalCount={totalCount} />
   </>
  );
}

 

ポイントはconst offset = (id - 1) * 6としている部分。

6記事ずつなので、paramsで渡されたidが4(/blog/page/4)なら18記事めがoffsetに設定される、というわけです。

そこからlimitで6記事を取得しているので、18記事目から24記事目が取得される4ページ目のブログ一覧ページが作成できます。

なお、ここでも、BlogPaginationコンポーネントを組み込んで、同様にページネーションを実現します。

 

おわりに

以上、ページネーションの実装方法でした!

上記はただ単に1.2.3.4.5....とページネーションの番号を表示していくだけですが、

PrevボタンやNextボタンを実装したいような場合、以下のやむちゃさんの記事も参考になるかと思います。

■【やむログ】Next.js × microCSSブログでページネーションを実装する (with Tailwind CSS)[シンプル]

https://blog.hpfull.jp/nextjs-microcms-pagination/

 

今回実装したものを応用して、「<」や「>」といったボタンの処理を用意してあげる感じですね。

それでは、今日はここまで。

 

HTNCode