昨日、久々に記事を書いたら、トップページで記事数が多すぎるのが気になったのでページネーションを追加した。
GatsbyJSはReact製なので、まさに最近いじっているからこのブログへ移行した当初よりReactは書けるようになったし、楽ちんと思いきや、GatsbyJSの仕組みそのものを忘れ去っていたのでかなり時間を溶かしてしまった。
gatsby-awesome-pagination をインストール
bash: title=bash1 2yarn add gatsby-awesome-pagination 3 4
gatsby-node.js を修正
jsx: title=gatsby-node.js(抜粋)1const { paginate } = require("gatsby-awesome-pagination") 2 3... // 省略 4 5exports.createPages = async ({ graphql, actions }) => { 6 7 ... // 省略 8 9 const result = await graphql(` 10 { 11 allMarkdownRemark( 12 sort: { order: DESC, fields: [frontmatter___date] } 13 limit: 1000 14 ) { 15 nodes { 16 id 17 fields { 18 slug 19 } 20 } 21 } 22 } 23 `) 24 25 ... // 省略 26 27 const posts = result.data.allMarkdownRemark.nodes 28 29 // ここで記事一覧を生成する 30 paginate({ 31 createPage, 32 items: posts, 33 itemsPerPage: 10, // 10件ずつ表示する 34 pathPrefix: ({ pageNumber }) => (pageNumber === 0 ? "/" : "/page"), 35 component: path.resolve(`./src/templates/index.js`), 36 }) 37 38 ... // 省略 39 40
gatsby-awesome-paginationから paginate()
関数を読み込む。
componentには src/templates/index.js
を指定する。
ここで注意すべきなのは、たしかgatsby-default-starterで作成していると src/pages/
に配置されていた気がするので src/templates/
に移動する必要があった。
gatsby-node.js
の全体はこんな感じ
jsx: title=gatsby-node.js1const path = require(`path`) 2const { createFilePath } = require(`gatsby-source-filesystem`) 3const { paginate } = require("gatsby-awesome-pagination") 4 5exports.onCreateNode = ({ node, getNode, actions }) => { 6 const { createNodeField } = actions 7 if (node.internal.type === `MarkdownRemark`) { 8 const value = createFilePath({ node, getNode, basePath: `pages` }) 9 const url = node.frontmatter.path 10 createNodeField({ 11 name: `slug`, 12 node, 13 value: url ? url : value, 14 }) 15 } 16} 17 18exports.createPages = async ({ graphql, actions }) => { 19 const { createPage } = actions 20 21 const result = await graphql(` 22 { 23 allMarkdownRemark( 24 sort: { order: DESC, fields: [frontmatter___date] } 25 limit: 1000 26 ) { 27 nodes { 28 id 29 fields { 30 slug 31 } 32 } 33 } 34 } 35 `) 36 37 if (result.errors) { 38 throw new Error(result.errors) 39 } 40 41 const posts = result.data.allMarkdownRemark.nodes 42 43 // ここで記事一覧を生成する 44 paginate({ 45 createPage, 46 items: posts, 47 itemsPerPage: 10, 48 pathPrefix: ({ pageNumber }) => (pageNumber === 0 ? "/" : "/page"), 49 component: path.resolve(`./src/templates/index.js`), 50 }) 51 52 // ここで記事単体を生成する 53 posts.forEach(post => { 54 createPage({ 55 path: post.fields.slug, 56 component: path.resolve(`./src/templates/article.js`), 57 context: { 58 slug: post.fields.slug, 59 }, 60 }) 61 }) 62} 63
index.js を修正
src/templates/index.js
を修正する。
props に pageContext を追加
jsx: title=src/templates/index.js(抜粋)1const IndexPage = ({ data, location, pageContext }) => { 2 return ( 3 ... ///省略 4 ) 5}); 6 7
gatsby-node.js
で paginate
関数を使ってページを生成すると、そのページには自動的に pageContext
が追加され、使えるようになる。
pageContext
には下記プロパティが定義されている。
- pageNumber - ページ番号(0始まり)
- humanPageNumber - ページ番号(1始まり)
- skip - GraphQL内で利用可能な $skipアイテム
- limit - GraphQL内で利用可能な $limitアイテム
- numberOfPages - 全ページ数
- previousPagePath - 1個前のページパス。
pathPrefix
で設定した形式になる。 - nextPagePath - 1個先のページパス。
pathPrefix
で設定した形式になる。
クエリ部分を修正
jsx: title=src/templates/index.js(抜粋)1 2... // 省略 3 4export const query = graphql` 5 query($limit: Int!, $skip: Int!) { //引数 $limit, $skip を追加 6 allMarkdownRemark( 7 sort: { fields: [frontmatter___date], order: DESC } 8 filter: { frontmatter: { type: { ne: "article" } } } 9 limit: $limit // 追加 10 skip: $skip // 追加 11 ) { 12 totalCount 13 edges { 14 node { 15 frontmatter { 16 title 17 year: date(formatString: "YYYY") 18 daymonth: date(formatString: "MM/DD") 19 categories 20 tags 21 } 22 fields { 23 slug 24 } 25 excerpt 26 } 27 } 28 } 29 } 30` 31
GraphQLのクエリに $limit, $skipを追加する。
ページャーを追加
jsx: title=src/templates/index.js(抜粋)1<Link to={props.pageContext.previousPagePath}>前の10件</Link> 2<Link to={props.pageContext.nextPagePath}>次の10件</Link> 3
pageContext
が使えるようになったことで、上記コンポーネントを記事一覧ページ内に埋め込むと「前の10件」、「次の10件」へ移動するリンクを埋め込める。
なお、このブログはGatsbyブログにページネーションを導入する | Jack-s blogさまの記事を参考に、そのままMaterial-UI Pagination Componentsに渡して埋め込む手法にした。
参考にさせていただいたサイト
/ 以上
よかったらシェアしてください!