microCMS

GatsbyJSでページネーションを実装してみよう

植田博樹

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

こんにちはかみむらです。

本記事では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を取得しているところです。これは全体のコンテンツ数を取得できます。また、一覧ページではskiplimitを使ってコンテンツ数を絞っています。

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をよろしくお願いいたします!

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

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

microCMSを無料で始める

microCMSについてお問い合わせ

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

お問い合わせ

microCMS公式アカウント

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

  • X
  • Discord
  • github

ABOUT ME

植田博樹
プロダクト開発と犬が好き。Jamstack アーキテクチャーやサーバレス技術に興味があります。