Gatsbyブログのページネーションの作り方
2021.11.27
この記事は約3分で読めます
目次
この記事の筆者:三好アキ
🔹 専門用語なしでプログラミングを教えるメソッドに定評があり、1200人以上のビギナーを、最新のフロントエンド開発入門に成功させる。
🔹 Amazonベストセラー1位を複数回獲得している『はじめてつくるReactアプリ with TypeScript』著者。
Amazon著者ページはこちら → amazon.co.jp/stores/author/B099Z51QF2
React、Next.js、TypeScriptなどのお役立ち情報や実践的コンテンツを、ビギナー向けにかみ砕いて無料配信中。登録はこちらから → 無料メルマガ登録
ページネーションとは?
記事数が増えたときに、1ページあたりに表示する記事の数を5つや10つなどに制限したいときに使うものがページネーションです。
1 2 3 4 5
Jamstackサイト制作でよく使われるGatsbyにページネーションを追加します。
本記事は、まず最初にGatsbyサイトに最もベーシックなブログ機能を実装し、そこにページネーションを追加するという流れです。
ロジック部分の説明だけなので、スタイルは各自お好みで適用してください。
なお、本記事ではGatsbyの最新バージョン(2021年11月時点)であるv4を使いますが、v2でもv3でも本記事と同じコードでページネーションの設置が可能です。
なお前後の記事へと移動する仕組みは、こちらの記事を参考にしてください。
ベーシックなブログ機能の作成
まずGatsbyのスターターサイトに、マークダウンのブログ機能を追加しましょう。
最初にスターターサイトをダウンロードするので、ターミナルで以下のコマンドを実行します。
npx gatsby new gatsby-starter-default https://github.com/gatsbyjs/gatsby-starter-default
次にブログ記事を一覧表示するblog.js
、個別記事を表示するsingleBlog.js
を作ります。
まずはblog.js
から始めます。
├──pages
│ ├── 404.js
│ ├── blog.js ←追加
│ ├── index.js
│ ├── pages-2.js
│ ├── using-ssr.js
│ └── using-typescript.tsx
次のコードを書きます。
// blog.js
import * as React from "react"
import { graphql, Link } from "gatsby"
const Blog = (props) => {
return (
<div>
<h1>ブログページ</h1>
{props.data.allMarkdownRemark.edges.map((singleBlog, index) =>
<div key={index}>
<h2><Link to={`/blog${singleBlog.node.fields.slug}`}>{singleBlog.node.frontmatter.title}</Link></h2>
<p>{singleBlog.node.frontmatter.date}</p>
</div>
)}
</div>
)
}
export default Blog
export const query = graphql`
query BlogQuery {
allMarkdownRemark(
sort: {fields: frontmatter___id, order: DESC}
) {
edges {
node {
fields {
slug
}
frontmatter {
date
summary
id
title
}
}
}
}
}
`
singleBlog.js
をtemplates
フォルダ内に作ります。
├──templates
│ ├── singleBlog.js ←追加
│ └── using-dsg.js
次のコードを書きます。
// singleBlog.js
import * as React from "react"
import { graphql } from "gatsby"
const SingleBlog = (props) => {
return (
<div>
<h1>{props.data.markdownRemark.frontmatter.title}</h1>
<p>{props.data.markdownRemark.frontmatter.date}</p>
<div dangerouslySetInnerHTML={{ __html: props.data.markdownRemark.html }} />
</div>
)
}
export default SingleBlog
export const query = graphql`
query SingleBlogQuery($slug: String!) {
markdownRemark(fields: { slug: { eq: $slug } }) {
frontmatter {
date
title
summary
id
}
html
}
}
`
次に、ブログ記事のマークダウンファイルを収納するフォルダをsrc
内に作ります。
├──src
│ ├── components
│ ├── data ←追加
│ ├── images
│ ├── pages
│ └── templates
data
内には6つのマークダウンファイルを作ります。
├── data
│ ├── first.md
│ ├── second.md
│ ├── third.md
│ ├── fourth.md
│ ├── fifth.md
│ └── sixth.md
それぞれのマークダウンファイルには、下のように基本的な情報を書きます。
// first.md
---
id: "1"
title: "記事1"
date: "2021-06-21"
summary: "記事1の要約"
---
1つ目の記事。
// second.md
---
id: "2"
title: "記事2"
date: "2021-06-22"
summary: "記事2の要約"
---
2つ目の記事。
// third.md
---
id: "3"
title: "記事3"
date: "2021-06-23"
summary: "記事3の要約"
---
3つ目の記事。
// fourth.md
---
id: "4"
title: "記事4"
date: "2021-06-24"
summary: "記事4の要約"
---
4つ目の記事。
// fifth.md
---
id: "5"
title: "記事5"
date: "2021-06-25"
summary: "記事5の要約"
---
5つ目の記事。
// sixth.md
---
id: "6"
title: "記事6"
date: "2021-06-26"
summary: "記事6の要約"
---
6つ目の記事。
これでブログのデータと、それを表示する部分ができました。
次は表示するための仕組みづくりです。
ブログ機能に必要なプラグインをインストールします。
npm install gatsby-transformer-remark
これと、デフォルトですでに入っているgatsby-source-filesystem
をgatsby-config.js
に追加します。
// gatsby-config.js
module.exports = {
siteMetadata: {
...
plugins: [
`gatsby-plugin-react-helmet`,
`gatsby-plugin-image`,
// ⬇ 追加
{
resolve: `gatsby-source-filesystem`,
options: {
name: `data`,
path: `${__dirname}/src/data`,
},
},
`gatsby-transformer-remark`,
// ⬆ 追加
{
resolve: `gatsby-source-filesystem`,
options: {
name: `images`,
path: `${__dirname}/src/images`,
},
},
`gatsby-transformer-sharp`,
...
gatsby-node.js
に、上で作ったコンポーネントにマークダウンファイルを流し込むためのコードを追加します。
// gatsby-node.js
// ⬇ 削除
exports.createPages = async ({ actions }) => {
const { createPage } = actions
createPage({
path: "/using-dsg",
component: require.resolve("./src/templates/using-dsg.js"),
context: {},
defer: true,
})
}
// ⬆ 削除
const path = require(`path`)
const { createFilePath } = require(`gatsby-source-filesystem`)
exports.onCreateNode = ({ node, getNode, actions }) => {
const { createNodeField } = actions
if (node.internal.type === `MarkdownRemark`) {
const slug = createFilePath({ node, getNode })
createNodeField({
node,
name: `slug`,
value: slug,
})
}
}
exports.createPages = async ({ graphql, actions }) => {
const { createPage } = actions
const result = await graphql(`
query {
allMarkdownRemark {
edges {
node {
fields {
slug
}
}
}
}
}
`)
result.data.allMarkdownRemark.edges.forEach(({ node }) => {
createPage({
path: `blog${node.fields.slug}`,
component: path.resolve(`./src/templates/singleBlog.js`),
context: {
slug: node.fields.slug,
},
})
})
}
ここまで加えた変更をすべて保存します。
gatsby develop
でGatsbyを起動し、http://localhost:8000/blog
をブラウザで開くと、ブログ機能が追加されているのがわかります。
これ以降、本題のページネーションを追加していきます。
ページネーションに必要なもの
ページネーションには次の3つが必要です。
1
gatsby-node.js
でblog.js
に表示する記事数を制限する仕組み
2
blog.js
ファイルの移動
3
paginationコンポーネント
それでは順番通りに作っていきます。
gatsby-node.jsで記事数を制限する
まず1つ目の、表示する記事数を制限するコードをgatsby-node.js
に追加します。
ここではblog.js
に表示される記事の数は2つとし、3つ目以降は次のページへと表示させます。
// gatsby-node.js
...
result.data.allMarkdownRemark.edges.forEach(({ node }) => {
createPage({
path: `blog${node.fields.slug}`,
component: path.resolve(`./src/templates/singleBlog.js`),
context: {
slug: node.fields.slug,
},
})
})
⬇追加
const blogs = result.data.allMarkdownRemark.edges
const blogsPerPage = 2
const numberPages = Math.ceil(blogs.length / blogsPerPage)
Array.from({ length: numberPages }).forEach((_, i) => {
createPage({
path: i === 0 ? `/blog` : `/blog/${i + 1}`,
component: path.resolve(`./src/templates/blog.js`),
context: {
limit: blogsPerPage,
skip: i * blogsPerPage,
numberPages,
currentPage: i + 1,
},
})
})
⬆追加
}
これにより、2記事ごとに新しいページが作られます。
limit
とskip
があるのは、blog.js
のGraphQLクエリで使うためで、context
の中に書いてblog.js
へと渡します。
blog.jsを移動する
ページネーション用に新しいblog-list.js
のようなコンポーネントを作り、そこに記事を表示することも可能ですが、今回はすでにあるblog.js
を使います。
しかしそうすると、いま打ったcreatePage
のコードで作った/blog
のURLと、pages
フォルダにあるblog.js
のURL/blog
が衝突するので、blog.js
をtemplates
フォルダへと移します。
src
.
.
├── templates
│ ├── blog.js ←pagesから移動
│ ├── singleBlog.js
│ └── using-dsg.js
.
.
そしてblog.js
には次のコードを追加します。
// blog.js
import * as React from "react"
import { graphql, Link } from "gatsby"
const Blog = (props) => {
return (
<div>
<h1>ブログページ</h1>
{props.data.allMarkdownRemark.edges.map((singleBlog, index) =>
<div key={index}>
<h2><Link to={`/blog${singleBlog.node.fields.slug}`}>{singleBlog.node.frontmatter.title}</Link></h2>
<p>{singleBlog.node.frontmatter.date}</p>
</div>
)}
</div>
)
}
export default Blog
export const query = graphql`
query BlogQuery ($skip: Int!, $limit: Int!) { // 追加
allMarkdownRemark(
sort: {fields: frontmatter___id, order: DESC}
limit: $limit // 追加
skip: $skip // 追加
) {
edges {
node {
fields {
slug
}
frontmatter {
date
summary
id
title
}
}
}
}
}
`
paginationコンポーネントの作成
paginationコンポーネントをcomponents
フォルダに作ります。
src
.
.
├── components
│ ├── header.js
│ ├── layout.css
│ ├── layout.js
│ ├── pagination.js ←追加
│ └── seo.js
.
.
そこに次のコードを書きます。
// pagination.js
import * as React from "react"
import { Link } from 'gatsby'
const Pagination = ({ pageContext }) => {
const { numberPages } = pageContext
return (
<h2>
{Array.from({ length: numberPages }, (_, i) => (
<Link key={`pagination-number${i + 1}`} to={`/blog/${i === 0 ? "" : i + 1}`}>
{i + 1}
</Link>
))}
</h2>
)
}
export default Pagination
そしてblog.js
に、いま作ったpaginationコンポーネントを読み込みます。
// blog.js
import * as React from "react"
import { graphql, Link } from "gatsby"
import Pagination from "../components/pagination" // 追加
const Blog = (props) => {
const { pageContext } = props // 追加
return (
<div>
<h1>ブログページ</h1>
{props.data.allMarkdownRemark.edges.map((singleBlog, index) =>
<div key={index}>
<h2><Link to={`/blog${singleBlog.node.fields.slug}`}>{singleBlog.node.frontmatter.title}</Link></h2>
<p>{singleBlog.node.frontmatter.date}</p>
</div>
)}
<Pagination pageContext={pageContext} /> // 追加
</div>
)
}
export default Blog
export const query = graphql`
query BlogQuery ($skip: Int!, $limit: Int!) {
allMarkdownRemark(
sort: {fields: frontmatter___id, order: DESC}
limit: $limit
skip: $skip
) {
edges {
node {
fields {
slug
}
frontmatter {
date
summary
id
title
}
}
}
}
}
`
変更を保存してgatsby develop
でGatsbyを起動させ、ブラウザでhttp://localhost:8000/blog
を開くと、ページネーションが追加されているのがわかります。
本記事では細かい説明を省略して足早に解説しましたが、Gatsbyについてよりくわしく知りたい方は、拙著「はじめてつくるGatsbyサイト」を参考にしてください。
なお、Gatsbyブログの記事ページ(singleBlog.js
)に前後の記事へのリンクを追加する方法は、こちらの記事を参考にしてください。
その他、Gatsbyに興味のある人は次の記事も参考にしてください。
メルマガ配信中
(from 三好アキ/エンジニア)
React、Next.js、TypeScriptなど最新のウェブ開発のお役立ち情報を、ビギナー向けにかみ砕いて無料配信中。
(*配信はいつでも停止できます)