ことばを学ぶ　LEARN GATSBY 週間 #5日目

こんばんは！

今回はページネーション機能を使ってみたいと思います.
ページネーション機能を利用するためのプラグインは何個かあるのですが、そのなかで一番便利な (悪く言うとプラグイン任せな) `awesome-pagination` を使います.
まずはプラグインをインストールします.

```
npm i gatsby-awesome-pagination
```
`gatsby-node.js` に以下を追加します.

```gatsby-node.js
const { paginate }= require('gatsby-awesome-pagination')

const bloglistTemplate = path.resolve('./src/templates/blog-list-template.js')
    paginate({
        createPage, 
        items: res.data.allMarkdownRemark.edges, 
        itemsPerPage: 3, 
        pathPrefix: '/bloglist', 
        component: bloglistTemplate,
      })
```
さらに、`bloglist.js` の名前を `blog-list-template.js` とし、`templates` フォルダに入れます.
そして、`blog-list-template.js` を以下のように編集します.

```blog-list-template.js
import React from 'react'
import { Link , graphql  } from 'gatsby'
import Layout from '../Layouts/common'

export const data = graphql`
query ($skip: Int!, $limit: Int!) {
    allMarkdownRemark (
        skip: $skip ,
        limit: $limit 
    ){
        
        edges {
            node {
                frontmatter {
                    title
                    date (formatString: "MMMM DD, YYYY")
                }
                excerpt
                fields{
                    slug
                }
            }
        }
    }
}
`
const BlogList = (props) => {
 
    return (
        <Layout>
            <h1>This is BlogList  </h1>
            <ol>
             {props.data.allMarkdownRemark.edges.map( ({node}) => {
                return (
                    <li key={node.fields.slug}>
                        <Link to={`/bloglist/${node.fields.slug}`} >
                            <h2>{node.frontmatter.title}</h2>
                            <p>{node.frontmatter.date}</p>
                        </Link>
                    </li>
                )
             })}
            </ol>
        </Layout>
    )
}

export default BlogList
```

開発用サーバーを起動して、`Bloglist` ページを見てみると、記事の数が3つになっています. これは、`gatsby-node.js` にて、`itemsPerPage` を `3` に設定したからです. `http://localhost:8000/bloglist/2` にアクセスしてみると、続きの3つの記事が現れます.
このように、ページネーション機能を使うと、記事数が多くなった時に見やすく、記事数が少ない場合でも多く見せることができます.

ここでいったん、上のコードの意味を簡単に考えてみましょう.　
ページネーションを行うには `4つの情報` が必要です.
それは、すべての記事情報 ( `items` )、1ページに何個の記事を載せるか ( `itemsPerPage` )、各ページにつけたいパス ( `pathPrefix` )、利用するテンプレート ( `component` ) です. 

これらの情報に加え、上の `$skip , $limit` を利用して、ページネーションしています.　この二つは変数で必ず正の整数が与えられます. 
例えば今6つ記事があり、`itemsPerPage` を `3` に指定したとき、`$limit` に `3` が与えられます. これは、1ページの記事の個数を `3` に限定 ( `limit` ) しているわけです.
`http://localhost:8000/bloglist/2` に移動したとき、`$limit` に加え、`$skip` には `3` が与えられます. なぜなら、`6` つの記事のうち最初の `3` つを飛ばしているから ( `skip` ) です.

つまり、ひとつのテンプレートを　使いまわして、**情報だけを変えている**から、あたかも、ページが切り替わっているように見えるというわけです. 

さて、`http://localhost:8000/bloglist/2` に行くためのリンクを作ってみましょう.
そのまま、`blog-list-template.js` にページリンクを書くと長くなるので、コンポーネントとして書いてみます.
`src/components` に `pageCon.js` を作成し、以下のように書きます.

```pageCon.js
import React from 'react'
import { Link } from 'gatsby'

const Page = ( {context} ) => {
    const { previousPagePath , nextPagePath ,humanPageNumber , numberOfPages} = context
    return (

        <div className="container">
        <nav className="pagination" >
          <ul>
            {previousPagePath && (
              <p>
                <Link to={previousPagePath}  className="newer-posts">
                  Prev
                </Link>
              </p>
            )}
            <p>
              <span className="page-number">
                Page {humanPageNumber} of {numberOfPages}
              </span>
            </p>
            {nextPagePath && (
              <p>
                <Link to={nextPagePath} className="older-posts">
                  Next 
                </Link>
              </p>
            )}
          </ul>
        </nav>
       
      </div>
    )
}

export default Page
```
`context` とは `pagination` によって渡されるオブジェクトで、自動的に以下の値を受け渡します.

>- pageNumber - ページ番号　( `0` から始まります )
>- humanPageNumber - ページ番号 ( `1` から始まります )
>- skip - 　さきほど `$skip` が使えたのは `context` で自動的に受け渡されているからです 
>- limit -   `$skip`と同様
>- numberOfPages - トータルのページ数
>- previousPagePath - 前のページへのパスを表します
>- nextPagePath - 次のページへのパスを表します

```
{previousPagePath && (   ...
```
この `&&` はもし、`previousPagePath` がなければ ( `= undefined` )、`&&` 以下は表示されないということです.

`blog-list-template.js` に以下を追加します.

```blog-list-template.js
import Page from '../components/pageCon'

 <Layout>
 ... (省略)
 <Page context = {props.pageContext} />
</Layout>
```

これで、`next` `previous` を押してページ移動することができます !

次回は、 `CSS` で少し形を整えた後、ページネーションを各記事間に設置、タグを実装してみたいと思います.

ここまで読んでくださって、ありがとうございました.