gatsby-starter-blog にページネーションを導入する
gatsby-starter-blog をベースに作成したブログの記事一覧ページにページネーションを導入してみました。
ページネーションは、gatsby-awesome-pagination というプラグインを使うことで簡単に実装できます。
インストール
gatsby-awesome-pagination プラグインをインストールします。
$ npm install gatsby-awesome-pagination
テンプレ化
記事一覧ページの URL は src/pages/index.js の配置から '/' となっていますが、今後はページ毎に異なる URL を動的に決定する必要があります。URL を動的に決定する例として、各記事ページはすでに src/template/blog-post.js をテンプレート化することで実現できているので、これと同様に index.js をテンプレート化すれば良さそうです。
そこで、src/pages/index.js を src/template 配下に移動します。
$ mv src/pages/index.js src/template/index.js
この index.js を、 blog-post.js と同様に gatsby-node.js の中でページ生成する処理を追加していきます。
ページを生成する
gatsby-node.js を編集します。
import { paginate } from 'gatsby-awesome-pagination'; exports.createPages = async ({ graphql, actions }) => { const result = await graphql( ` { allContentfulPost() { edges { node { // 取得したい要素 } } } } ` ) const posts = result.data.allContentfulPost.edges paginate({ createPage, items: posts, itemsPerPage: 10, component: path.resolve('src/templates/index.js'), pathPrefix: ({ pageNumber }) => ( pageNumber === 0 ? '/' : '/page' ) }) ... }
gatsby-awesome-pagination を import して paginate を使えるようにします。paginate の中では createPage を含め、以下のようなパラメータを設定します。
items
: ページ内で表示する記事の配列。ここでは GraphQL で取得した配列を指定します。itemsPerPage
: 1ページあたりに表示する記事の数。ここでは 10 とします。component
: テンプレートのファイル。ここでは index.js を指定します。pathPrefix
: 各ページのパスを指定します。トップページは '/' 、2ページ目以降は '/page/2', '/page/3' となるようにしています。
これにより、テンプレートとして指定した index.js で以下のような Context が自動的に利用できるようになります。
パラメータ | 説明 |
---|---|
pageNumber | ページ番号 (0始まり) |
humanPageNumber | ページ番号 (1始まり) |
skip | スキップする記事の数。GraphQL で $skip で利用できます |
limit | ページ内の記事の最大数。GraphQL で $limit で利用できます |
numberOfPages | ページ数 |
previousPagePath | 前のページのパス |
nextPagePath | 次のページのパス |
GraphQL の編集
上記の $skip と $limit を利用して、src/template/index.js における GraphQL のクエリを修正します。
export const pageQuery = graphql` query($skip: Int!, $limit: Int!) { allContentfulPost(skip: $skip, limit: $limit) { edges { node { ...
この時点で、ページが作成されて各ページに動的な URL が紐づいている状態となります。ブラウザで /
(1ページ目) , /page/2
(2ページ目) のパスにアクセスすると各ページが表示されていることが確認できるかと思います。
前後のページのリンクを付ける
前のページ、次のページに遷移できるように各ページ内にリンクを設置します。
const BlogIndex = ({ data, location, pageContext }) => { return ( ... <ul> <li> {pageContext.previousPagePath && ( <Link to={pageContext.previousPagePath} rel="prev"> ← Newer </Link> )} </li> <li> {pageContext.nextPagePath && ( <Link to={pageContext.nextPagePath} rel="next"> Older → </Link> )} </li> </ul> )
props として pageContext が受け取れるようになっています。この Context の中で、前のページのパス previousPagePath
と 次のページのパス nextPagePath
が取得できるので、これを使えばリンクが簡単に作れます。
ちなみに、最初のページの previousPagePath
と 最後のページの nextPagePath
は undefined となるので、そのときはリンクを表示しないようにします。
あとは適当に style を設定します。
<ul style={{ display: `flex`, flexWrap: `wrap`, justifyContent: `space-between`, listStyle: `none`, padding: 0, }} >
こんな感じでリンクが追加できました。