【GatsbyJS】ブログにPaginationを実装してみた
2021-01-11
Content
はじめに
おはようございます!こんにちは!こんばんは!
のふのふ(@rpf_nob)と申します!!都内のスタートアップでフロントエンドエンジニアとして働いています。
記事数が増えてきたこともあって、そろそろページネーションがあったほうがいいかな思ったので実装してみました。
公式ページに追加方法も記載されていますが、今回はgatsby-awesome-paginationというパッケージで簡単にできたので、こちらで解説します!!
- 前提
 - パッケージのインストール
 - templates フォルダ配下に pages/index.js を移動
 - gatsby-node.js の編集
 - pages/index.js の編集
 - components/pagenation.js の作成
 - まとめ
 
前提
このブログは GatsbyJS の gatsby-starter-blog のテンプレートから作成しています。
ソースコードはこちら(参考になったという方は ⭐️ をポチッと押していただけると嬉しいです〜 🙇♂️)
パッケージのインストール
今回はgatsby-awesome-paginationを使って実装します。
$npm install --save gatsby-awesome-paginationこちらのパッケージで簡単にページネーションを実装できます。
templates フォルダ配下に pages/index.jsx を移動
まず初めに pages/index.jsx を src/templates/homepage フォルダ配下に移動します。
gatsby-node.js の編集
次にインストールしたgatsby-awesome-paginationから paginate をインポートします。
const { paginate } = require("gatsby-awesome-pagination");そして以下のように、createPages に追記します。
template に先ほど移動した pages/index.js を指定します。
pathPrefix に設定する値で、1 ページ目は ROOTURL/で 2 ページ目以降は ROOTURL/page/2になるように設定します。
exports.createPages = async ({ graphql, actions }) => {
  const { createPage } = actions;
  const blogPost = path.resolve(`./src/templates/homepage/index.jsx`);
  const result = await graphql(
    `
      {
        posts: allMarkdownRemark(sort: { fields: [frontmatter___date], order: DESC }, limit: 1000) {
          ・・・
      }
    `
  );
  if (result.errors) {
    throw result.errors;
  }
  const posts = result.data.posts.edges;
  paginate({    createPage,    items: posts,    itemsPerPage: 5,    component: template,    pathPrefix: ({ pageNumber }) => (pageNumber === 0 ? "/" : "/page"),  });こちらで gatsby-node.js の編集は完了です。
src/templates/homepage/index.jsx の編集
次に src/templates/homepage/index.jsx を編集します。
まず始めに pageQuery で skip と limit を取得できるようにします。
export const pageQuery = graphql`
  query($skip: Int!, $limit: Int!) {    site {
      ・・・
    }
    allMarkdownRemark(
      sort: { fields: [frontmatter___date], order: DESC }
      skip: $skip      limit: $limit    ) {
      edges {
        ・・・
      }
    }
  }
`;次にテンプレートのコンポーネントに pageContext がわたってくるので props として受け取り、次で作成する Pagenation コンポーネントを設置して、同じように pageContext を props で渡してあげます。
const BlogIndex = ({ data, location, pageContext }) => {  const siteTitle = data.site.siteMetadata.title;
  const author = data.site.siteMetadata.author.name;
  const posts = data.allMarkdownRemark.edges;
  return (
    <div>
      <Layout location={location} title={siteTitle} author={author}>
        <SEO title="All posts" />
        ・・・
        <Pagenation pageContext={pageContext} />        <Adsense />
        <Adsense />
      </Layout>
    </div>
  );
};components/pagenation/index.jsx の作成
最後に Pagenation コンポーネントを作成します。
今回は material ui のページネーションコンポーネントを使います。
ソース全文
import React from "react";
import { navigate } from "gatsby";
import { makeStyles } from "@material-ui/core/styles";
import { Pagination } from "@material-ui/lab";
const useStyles = makeStyles(theme => ({
  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
        size="small"
        defaultPage={humanPageNumber}
        count={numberOfPages}
        color="primary"
        onChange={handleChange}
      />
    </div>
  );
};
export default Pagenation;pageContext から numberOfPages と humanPageNumber を取り出します。
- numberOfPages は総ページ数
 - humanPageNumber は現在のページ番号
 
material ui の Pagination コンポーネントを設置して以下渡します。
- defaultPage に humanPageNumber を渡す
 - count に numberOfPages を渡す
 - onChange に handleChange を渡す(後述)
 
defaultPage を設定してあげないと、ページ遷移時に1ページに目に見た目だけ戻ってしまいます。
handleChange はページ番号クリック時の処理を記載します。
value にページ番号が渡ってくるので、それに対応したページに遷移してあげます。 ページ遷移には gatsby から navigate をインポートしてこちらを使います。react-router の history.push みたいなものです。
これで次のようにページネーションがいい感じに実装できました!!