gatsby-awesome-paginationの追加
yarn
でgatsby-awesome-pagination
プラグインを追加する。
yarn add gatsby-awesome-pagination
gatsby-node.jsの編集
ページの割り付けをするpaginate
関数をgatsby-node.js
にインポートして設定。
前提としてGatsby公式のgatsby-starter-blogを使っているものとする。
公式ページでは、import
を使うように記載されているが、const
でgatsby-awesome-pagination
を読み込む。
gatsby-node.js
const path = require(`path`)
const { createFilePath } = require(`gatsby-source-filesystem`)
const { paginate } = require(`gatsby-awesome-pagination`)
exports.createPages = async ({ graphql, actions, reporter }) => {
const { createPage } = actions
// Define a template for blog post
const blogPost = path.resolve(`./src/templates/blog-post.js`)
// Get all markdown blog posts sorted by date
const result = await graphql(
`
{
allMarkdownRemark(
sort: { fields: [frontmatter___date], order: ASC }
limit: 1000
) {
nodes {
id
fields {
slug
}
}
}
}
`
)
if (result.errors) {
reporter.panicOnBuild(
`There was an error loading your blog posts`,
result.errors
)
return
}
const posts = result.data.allMarkdownRemark.nodes
// Create blog posts pages
if (posts.length > 0) {
posts.forEach((post, index) => {
const previousPostId = index === 0 ? null : posts[index - 1].id
const nextPostId = index === posts.length - 1 ? null : posts[index + 1].id
createPage({
path: post.fields.slug,
component: blogPost,
context: {
id: post.id,
previousPostId,
nextPostId,
},
})
})
}
// Create your paginated pages paginate({ createPage, items: posts, itemsPerPage: 10, pathPrefix: ({ pageNumber }) => (pageNumber === 0 ? "/" : "/page"), component: path.resolve('src/templates/index.js') })}
exports.onCreateNode = ({ node, actions, getNode }) => {
const { createNodeField } = actions
if (node.internal.type === `MarkdownRemark`) {
const value = createFilePath({ node, getNode })
createNodeField({
name: `slug`,
node,
value,
})
}
}
index.js
をtemplates
フォルダの下に移動しておく。
index.jsの編集
GraphQLのクエリをページネーションに対応させるため、skip
とlimit
を組み込むように修正。
<footer>
にcomponents/pagination
からPagenation
(綴りに注意)をインポートし、ページネーションとして表示するように追記。
src/templates/index.js
import * as React from "react"
import { Link, graphql } from "gatsby"
import Layout from "../components/layout"
import Seo from "../components/seo"
import Pagenation from "../components/pagination"
const BlogIndex = ({ data, location, pageContext }) => { const siteTitle = data.site.siteMetadata?.title || `Title`
const posts = data.allMarkdownRemark.nodes
if (posts.length === 0) {
return (
<Layout location={location} title={siteTitle}>
<Seo title="All Posts" />
<p>
No blog posts found. Add markdown posts to "content/blog" (or the
directory you specified for the "gatsby-source-filesystem" plugin in
gatsby-config.js).
</p>
</Layout>
)
}
return (
<Layout location={location} title={siteTitle}>
<Seo title="All Posts" />
<ol style={{ listStyle: `none` }}>
{posts.map(post => {
const title = post.frontmatter.title || post.fields.slug
return (
<li key={post.fields.slug}>
<article
className="post-list-item"
itemScope
itemType="http://schema.org/Article"
>
<header>
<h3>
<Link to={post.fields.slug} itemProp="url">
<span itemProp="headline">{title}</span>
</Link>
</h3>
<small>{post.frontmatter.date}</small>
</header>
<section>
<p
dangerouslySetInnerHTML={{
__html: post.frontmatter.description || post.excerpt,
}}
itemProp="description"
/>
</section>
</article>
</li>
)
})}
</ol>
<footer> <Pagenation pageContext={pageContext} /> </footer> </Layout>
)
}
export default BlogIndex
export const pageQuery = graphql`
query ($skip: Int!, $limit: Int!) { site {
siteMetadata {
title
}
}
allMarkdownRemark(
sort: { fields: [frontmatter___date], order: DESC }
skip: $skip limit: $limit ) {
nodes {
excerpt
fields {
slug
}
frontmatter {
date(formatString: "YYYY.MM.DD")
title
description
}
}
}
}
`
pagination.jsの追加
footer
にページネーションのためのページ番号や移動アイコンを表示するため、
pagination.js
を作成する。
Material UIを使用するため、事前にプラグインをインストール。
yarn add gatsby-plugin-material-ui @material-ui/core @material-ui/lab @material-ui/styles
material-ui
をインポートして、footer
に表示するPagenation
を定義。
src/components/pagination.js
import React from "react"
import { navigate } from "gatsby"
import { makeStyles } from "@material-ui/core/styles"
import { Pagination } from "@material-ui/lab"
const useStyles = makeStyles({
root: {
display: `flex`,
flexWrap: `wrap`,
justifyContent: `center`,
alignItems: "center",
},
});
const Pagenation = ({ pageContext }) => {
const classes = useStyles()
const { numberOfPages, humanPageNumber } = pageContext
const handleChange = (_event, value) => {
value === 1 ? navigate(`/`) : navigate(`/page/${value}`)
}
return (
<div className={classes.root}>
<Pagination
variant="outlined"
defaultPage={humanPageNumber}
count={numberOfPages}
onChange={handleChange}
/>
</div>
)
}
export default Pagenation