こんにちはかみむらです。
本記事ではGatsbyJSでページネーションを実装していきます。
以前に書いたGatsbyJS + microCMSでJamstackなオウンドメディアを作ろう
作ろうの拡張版になります。本記事はこのチュートリアルを終えてる前提で話を進めていきます。
今回の作成イメージは下記の画像のような、1から順番に数字が並んでいるページネーションです。
前提
下記のバージョンで開発を行っています。バージョンの差異によって若干機能が異なる可能性があります。
- GatsbyJS v3.11.0
- gatsby-source-microcms v1.2.1
コンポーネントの作成
はじめに、ページネーションを作成するためのベースとなるコンポーネントを作成します。components/pagination.js
を作成してください。
こちらはコードの全体像です。
//components/pagination.js
import React from "react"
import { Link } from "gatsby"
export const Pagination = ({ totalCount }) => {
const PER_PAGE = 5
const range = (start, end) => [...Array(end - start + 1)].map((_, i) => start + i)
return (
<ul>
{range(1, Math.ceil(totalCount / PER_PAGE)).map((number, index) => (
<li key={index}>
<Link to={`/blog/page/${number}`}>{number}</Link>
</li>
))}
</ul>
)
}
このコンポーネントの説明は以下になります。
① range
の引数に(start, end)を与えて、その値を元に配列を作成します。これで、totalCount
が20でPER_PAGE
が5とすると(20 /5)で4が返ります。これはページネーションのリスト数になります。
② rangeで作成した配列をmapして各数値を取り出します。
実際にコンポーネントのtotalCount
に数値を入れると以下のようになります。pages
内のindex.js
にインポートして確認してみましょう。
<Pagination totalCount={20} />
実装通り4つのリストを作成することができました。これをベースとしてページネーションを実装していきます。
このコンポーネントはNext.js(SSG)でページネーションを実装してみようでも使用しています。Next.jsを利用している場合はこちらの記事も一読してください。
一覧ページでのページネーション
次に、一覧ページのページネーションを実装していきましょう。
それでは、pages/index.js
にロジックを書いていきます。
import React from "react"
import { graphql, Link } from "gatsby"
import Layout from "../components/layout"
import SEO from "../components/seo"
import { Pagination } from "../components/pagination"
const IndexPage = ({ data }) => (
<Layout>
<SEO title="Home" />
<ul>
{data.allMicrocmsBlog.edges.map(({ node }) => (
<li key={node.blogId}>
<Link to={`/blog/${node.blogId}`}>{node.title}</Link>
</li>
))}
</ul>
<Pagination totalCount={data.allMicrocmsBlog.totalCount} />
</Layout>
)
export default IndexPage
export const query = graphql`
query {
allMicrocmsBlog(limit: 5, skip: 0) {
totalCount
edges {
node {
blogId
title
}
}
}
}
`
ポイントはtotalCount
を取得しているところです。これは全体のコンテンツ数を取得できます。また、一覧ページではskip
とlimit
を使ってコンテンツ数を絞っています。skip
は何件目から取得するかを指定します。microCMS本来のクエリはoffset
です。ですがGatsbyJSでoffsetを実現するにはskip
を利用します。これはGatsbyJSの
Graphql Query Optionsです。詳しくはskipのドキュメントを参照してください。limit
は取得件数を指定します。ここでは5件取得しています。
試しに、microCMSの記事数を10件作成して検証してみましょう。上から10~6件目のコンテンツが取得できます。
個別のページネーション
次に、絞り込みを行った個別のページを作成していきます。
SSGでページネーションを作成する場合は、SSRと違って/page/1
、/page/2
のようにして、各ページ毎にコンテンツを取得するのがベターです。動的なページを生成するために、gatsby-node.js
に設定内容を追記してみましょう。
const path = require("path")
exports.createPages = async ({ graphql, actions }) => {
const { createPage } = actions
const result = await graphql(
`
{
allMicrocmsBlog {
totalCount
}
}
`
)
if (result.errors) {
throw result.errors
}
const PerPage = 5
const pageCount = Math.ceil(result.data.allMicrocmsBlog.totalCount / PerPage)
for (let i = 0; i < pageCount; i++) {
createPage({
path: `/blog/page/${i + 1}`,
component: path.resolve("./src/template/blog-page.js"),
context: {
limit: PerPage,
skip: i * PerPage,
},
})
}
}
先程と同じく、GraphQLのクエリを使ってtotalCount
を取得しています。
const result = await graphql(
`
{
allMicrocmsBlog {
totalCount
}
}
`
)
取得したtotalCount
の情報を元にページ数を割り出します。totalCount
が10でPerPage
が5の場合、pageCount
は2になります。
const pageCount = Math.ceil(result.data.allMicrocmsBlog.totalCount / PerPage)
そして、ページ数を元に動的なページを作成します。createPage
はページを動的に作成するGatabyJSのAPIです。pathは動的ページのURLになります。
for (let i = 0; i < pageCount; i++) {
createPage({
path: `/blog/page/${i + 1}`,
component: path.resolve("./src/template/blog-page.js"),
context: {
limit: PerPage,
skip: i * PerPage,
},
})
}
createPageの引数オブジェクト内のcomponentプロパティでは、ページを生成する際のテンプレートを指定しています。src/template
フォルダを作成して、blog-page.js
を下記の内容で作成しましょう。
import React from "react"
import { graphql, Link } from "gatsby"
import Layout from "../components/layout"
import SEO from "../components/seo"
import { Pagination } from "../components/pagination"
const BlogPage = ({ data }) => {
return (
<Layout>
<SEO title="Home" />
<ul>
{data.allMicrocmsBlog.edges.map(({ node }) => (
<li key={node.blogId}>
<Link to={`/blog/${node.blogId}`}>{node.title}</Link>
</li>
))}
</ul>
<Pagination totalCount={data.allMicrocmsBlog.totalCount} />
</Layout>
)
}
export default BlogPage
export const query = graphql`
query ($limit: Int!, $skip: Int!) {
allMicrocmsBlog(limit: $limit, skip: $skip) {
edges {
node {
id
blogId
title
}
}
totalCount
}
}
`
queryの引数にある$limit
と$skip
は、gatsby-config.jsで作成したcontextの値を受け取っています。この値を元にコンテンツにフィルタをかけています。
これで、ページネーションの2をクリックすると1~5件のコンテンツを取得することができます。
おわりに
今回はGatsbyJSのページネーションについて解説しました。ページネーションはWeb制作において重要なコンポーネントになります。ぜひ、この記事がお役に立てば嬉しいです。
-----
microCMSは日々改善を進めています。
ご意見・ご要望は管理画面右下のチャット、公式Twitter、メールからお気軽にご連絡ください!
引き続きmicroCMSをよろしくお願いいたします!