Gatsbyブログにページングを導入する

2021年06月03日

gatsby-starter-blogで作った本ブログのトップページをページャ対応します。

方針

gatsby-awesome-pagination を利用します。

gatsby-awesome-pagination をインストール

$ npm install gatsby-awesome-pagination

インストールはnpm installで。

このプラグインはただのutilityライブラリなので、gatsby-config.js への設定追加は不要です。

トップページをテンプレート化する

$ mv src/pages/index.js src/templates/index.js

記事一覧を10記事毎にページ分割するため、動的にURLを決定する必要があります。固定ページとしてsrc/pages配下にindex.jsとして実装していたものを gatsby-node.js から createPageで動的なページ生成するように変更します。

paginateで10記事毎に区切って画面生成するように修正する

gatsby-node.js をカスタマイズします。

const { paginate } = require("gatsby-awesome-pagination")


const posts = result.data.postsRemark.edges

paginate({
    createPage,
    items: posts,
    itemsPerPage: 10,
    component: path.resolve("src/templates/index.js"),
    pathPrefix: ({ pageNumber }) => (
        pageNumber === 0 ? "/" : "/page"
    )
})

gatsby-awesome-paginationが提供する paginate がcreatePageのラッパーとなり、良しなにページ分割とURLの割当を行ってくれます。

パラメータの意味は以下となります。

items
ブログ記事の配列全体を渡します。 もともとposts変数にマークダウン記事全てを取得格納するようになっているのでこれを指定すればokです。

itemsPerPage
ページングの単位です。 10記事毎に画面分割するので10とします。

component
ページテンプレート化したトップページのjsファイルを指定します。

pathPrefix
分割した画面それぞれのURLルールを決定します。 pageNumberは0からカウントされるので、1ページ目は0、2ページ目は1、のようなインクリメントルールとなります。1ページ目はルートパス、2ページ目移行は /page/ 配下に自動連番となるように調整します。

GraphQLを修正する

src/templates/index.js に修正を加えます。

-  query {
+  query($skip: Int!, $limit: Int!) {

...

-    allMdx(sort: { fields: [frontmatter___date], order: DESC }) {
+    allMdx(sort: { fields: [frontmatter___date], order: DESC }, skip: $skip, limit: $limit) {

GraphQLを修正します。skipとlimit がプラグインにより追加されるので、allMdxによる記事の収集条件に指定を加えます。

ここまでの手順で「記事10件毎に画面分割を行い、各画面に一意なURLを割り当てた状態」となります。

実際にブラウザでURLを叩いてみましょう。

1ページ目 /  
2ページ目 /page/2  
3ページ目 /page/3
...

前後ページへのページャリンクを付ける

ページ分割はできましたがこのままだと2ページ目以降へのリンク導線がありません。

ページの前後移動リンクを作ります。

const BlogIndex = ({ data, location, pageContext }) => {

        //...
        
        <div className={Styles.pager}>
            <Link to={pageContext.previousPagePath}>←前へ</Link>
            <Link to={pageContext.nextPagePath}>次へ→</Link>
        </div>

かなり手抜きです。よしなにデザインを作ってカスタムしてください。

ポイントは、テンプレート化してcreatePage経由で生成する画面になったことでpageContextが受け取れるようになったことです。

pagenateを通してページ生成すると、pageContextにnextPagePath、previousPagePathがパラメータとして渡ってきます。これらが前後ページのURLパスとなっており、リンクにするとページャになります。

まとめ

gatsbyブログの記事一覧をページ分割してみました。

いかがでしたでしょうか。

とても簡単だったと思います。

このブログはほとんどデフォルトの状態で運用しているので、他にも徐々に拡張していきたいと思います。

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

良きReactライフを!


Web系エンジニアでPython好き。バックエンド/フロントエンド問わずマルチな方面でエンジニアリングしています。