published on : 2019.10.16Web制作

#2 Gatsby + WordPress REST APIでブログを作ろう【ページネーションの設置編】

前回の「Gatsby + WordPress REST APIでブログを作ろう【導入+基本構成編】」に引き続きトップページにページネーションを設置していきます

ページネーションを追加するのにGatsby-paginateを使います。

yarn add gatsby-paginate

gatsby-node.jsで「gatsby-paginate」をrequireします

gatsby-node.js
const createPaginatedPages = require('gatsby-paginate')

これで「createPaginatedPages」が使えるようになるので更に以下のコードをgatsby-node.jsに追加します

gatsby-node.js
createPaginatedPages({
    edges: result.data.allWordpressPost.edges,
    createPage: createPage,
    pageTemplate: 'src/templates/Pagination.js',
    pageLength: 5,
    pathPrefix: 'posts',
  })

前回の記事に沿って制作されている方は「const BlogPosts = result.data.allWordpressPost.edges」がすでにあるかと思うので、「edges : BlogPosts,」でも大丈夫です

templatesの中にPagination.jsを作ります(名前はなんでもオッケーです)
pageLengthは1ページにいくつ記事を表示するかの設定

サンプルのコードはgatsbyのドキュメントに記載してあります

Pagination.js
import React from 'react'
import Link from 'gatsby-link'

const NavLink = props => {
  if (!props.test) {
    return <Link to={props.url}>{props.text}</Link>
  } else {
    return <span>{props.text}</span>
  }
}

const Pagination = ({ pageContext }) => {
  const { group, index, first, last, pageCount } = pageContext
  const previousUrl = index - 1 === 1 ? '/' : (index - 1).toString()
  const nextUrl = (index + 1).toString()

  return (
    <div>
      <h4>{pageCount} Pages</h4>

      {group.map(({ node }) => (
        <div key={node.slug} className={"post"}>
          <Link to={node.slug}>
            <h3>{node.title}</h3>
          </Link>
          <div className={"post-content"} dangerouslySetInnerHTML={{__html: node.excerpt}} />
          {node.date}
        </div>
      ))}
      <div className="previousLink">
        <NavLink test={first} url={previousUrl} text="Go to Previous Page" />
      </div>
      <div className="nextLink">
        <NavLink test={last} url={nextUrl} text="Go to Next Page" />
      </div>
    </div>
  )
}
export default Pagination

この状態でgatsby developをして/postsにいってみると、、、

こんな感じでページが表示されますが、タイトルや日付は表示されていません。

gatsby-node.jsのallWordpressPostに表示したいものを追加します

gatsby-node.js
allWordpressPost {
        edges {
          node {
            id
            title
            date
            excerpt
            slug
            wordpress_id
          }
        }
      }

これでgatsby developをし直すとちゃんとタイトルや日付が表示されます

このままですと、「Go to Next Page」のUrlが「〜/posts/2」ではなく「〜/2」になっているのでちゃんと次のページが表示されません

こんな感じで404ページに飛ばされます

gatsby-node.jsで「pathPrefix」を指定していればgatsbyがパスを理解して生成してくれるはずなのですが、ちゃんとならないので修正します

Pagination.jsのリンク先にposts/を追加するだけです

Pagination.js
<div className="previousLink">
  <NavLink test={first} url={"posts/" + previousUrl} text="Go to Previous Page" />
</div>
<div className="nextLink">
  <NavLink test={last} url={"posts/" + nextUrl} text="Go to Next Page" />
</div>

これでUrlが「〜/posts/2」になります

Urlに飛ぶとちゃんとページが表示されます

これで基本的なページネーションの実装は終わりです

あとは必要に応じてpathPrefixを変えたり、トップページにページネーションを追加したりしてください^ ^

*gatsby-imageとgatsby-paginateを一緒に使う時に注意

ページネーションの実装が終わってサムネ画像も表示したいってなった時にgatsby-node.jsに…GatsbyImageSharpFluidを追記してもエラーが出ます

エラー内容:
Error: unknown fragment ...GatsbyImageSharpFluid

gatsby-node.js内では…GatsbyImageSharpFluidは有効なフラグメントとして認識されないみたいなので使えません。

ベストの解決策かはわかりませんが、…GatsbyImageSharpFluidの代わりに以下を追加すると表示されます

gatsby-node.js
featured_media {
              localFile {
                childImageSharp {
                  fluid(maxWidth: 1000) {
                    src
                    srcSet
                    aspectRatio
                    sizes
                    base64
                  }
                }
              }
            }

fixedでも同じで…GatsbyImageSharpFixedも使えないので上のように書き換えれば表示されます

Pagination.js
import React from 'react'
import Link from 'gatsby-link'
import Img from "gatsby-image"

const NavLink = props => {
  if (!props.test) {
    return <Link to={props.url}>{props.text}</Link>
  } else {
    return <span>{props.text}</span>
  }
}

const Pagination = ({ pageContext }) => {
  const { group, index, first, last, pageCount } = pageContext
  const previousUrl = index - 1 === 1 ? '/' : (index - 1).toString()
  const nextUrl = (index + 1).toString()

  return (
    <div>
      <h4>{pageCount} Pages</h4>

      {group.map(({ node }) => (
        <div key={node.id} className={"post"}>
          <Link to={`/${node.slug}`} >
            {node.featured_media &&
              <div>
                <Img
                  fluid={node.featured_media.localFile.childImageSharp.fluid}
                  alt={node.title}
                />
              </div>
            }
            <h3>{node.title}</h3>
          </Link>
          <div className={"post-content"} dangerouslySetInnerHTML={{__html: node.excerpt}} />
          {node.date}
        </div>
      ))}
      <div className="previousLink">
        <NavLink test={first} url={`/${"posts/" + previousUrl}`} text="Go to Previous Page" />
      </div>
      <div className="nextLink">
        <NavLink test={last} url={`/${"posts/" + nextUrl}`} text="Go to Next Page" />
      </div>
    </div>
  )
}
export default Pagination

こんな感じで表示されました

以上でページネーションの設置は終わりです!

必要に応じてカスタマイズしてみてください^ ^

Share if you like

Commentなんでも気軽にどうぞ^ ^

Author
Web Designer

Kentaro Koga

福岡を拠点のクリエイターチーム「Fump」として活動をしています。

写真や動画の撮影やモノ作りが好きで、趣味は旅・カメラ・テニス・筋トレ・サウナ・レザークラフトです。

twitterアイコンinstagramアイコンfacebookアイコン