【GatsbyJS】ブログにPaginationを実装してみた
2021-01-11Content
はじめに
おはようございます!こんにちは!こんばんは!
のふのふ(@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 みたいなものです。
これで次のようにページネーションがいい感じに実装できました!!