作成日時: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ファイルを作成
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コンポーネントをブログ一覧用のコンポーネントに組み込みます。
※不要な部分は省略しています
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