material-ui-flat-paginationを使ってページネーションを実装する

「Material-UI Pagination」等で調べると、
最初に出てくるのがMaterial-UIが用意してくれている「[TablePagination API - Material-UI](https://material-ui.com/api/table-pagination/)」です。
見た目はこんな感じ。

![1.png](https://qiita-image-store.s3.amazonaws.com/0/327745/348b699f-4e09-3450-30e3-a508d5552b6e.png)

（[デモコード](https://material-ui.com/demos/tables/#custom-table-pagination-action)）

結構スタイルが限られてしまってるので、良さそうなライブラリを見つけました！
[material-ui-flat-pagination - npm](https://www.npmjs.com/package/material-ui-flat-pagination)

`material-ui-flat-pagination`で実際に実装したメモを残すことにします。

##前準備
Material-UIを使用しているのを前提に進めていきます！
まずは公式ドキュメント通り、インストールしていきましょう。

```shell
$ npm install material-ui-flat-pagination
```

また、公式ドキュメントにある `createMuiTheme`, `MuiThemeProvider`系の説明は「[Theme](https://material-ui.com/customization/themes/)」にあります♫👀


##いざ、実装

`material-ui-flat-pagination`のドキュメントを見る限り、めっちゃ簡単そうです！

###1.`import`してとりあえず<Pagination />タグを置いてみる

Exampleに書いてある通りにimportし、`<Pagination />`タグを設置していこうと思います。
コンポーネントのimport群に下を追加します。

```javascript
import Pagination from "material-ui-flat-pagination";
```

ローカルステートにページャーに必要な`offset`と、１ページに表示させる数n個を指定します。

```javascript
class Example extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      ...
      offset: 0,
      parPage: 10,
      ...
    }
  }
  ...

}
```

今回はリスト10個ずつ表示されるよう、`perPage: 10`を設定してみました。
お次に`<Pagination />`と`onClick`時の関数`handleClickPagination`を実装していきます！

```javascript
...
handleClickPagination = offset => {
  this.setState({ offset })
}

render() {
  return (
    <div>
      <ul>
        {this.state.userList
          .slice(offset, offset + parPage)
          .map(user => {
            <li>{user.id}: {user.name}</li>
          })
        }
      </ul>

      <Pagination
        limit={this.state.parPage}
        offset={this.state.offset}
        total={this.state.userList.length}
        onClick={(e, offset) => this.handleClickPagination(offset)}
      />
    </div>
  )
}

...省略
```

こんな感じでしょうか！
`total`にはループ表示したいリストの総数を入れます。なので`total={配列.length}`と入れてあげればOKです。
スタイルをつけてないと、デフォルトだとこんな感じです。

![demo.gif](https://qiita-image-store.s3.amazonaws.com/0/327745/3e9caca8-32ff-d6c9-5791-68f0f85783e8.gif)

画像元：[npm material-ui-flat-pagination](https://www.npmjs.com/package/material-ui-flat-pagination)


あとは軽くcssで肉付けして完了です。

###2.スタイル調整していい感じにする

`classes`でクラス名を指定し、また、リストが10個以下の時はページャーを表示させたくなかったので、`length > 10`で囲っています。

```javascript
pageNavi: {
  textAlign: 'center',
  '& > button': {
    width: 50,
    height: 50,
    margin: '0 5px',
    borderRadius: 5,
    border: '1px solid gray'
  }
},
pageNaviCurrent: {
  cursor: 'default',
  backgroundColor: 'yellow',
  '&:hover': {
    backgroundColor: 'yellow'
  }
},
pageNaviText: {
  color: 'black'
},
pageNaviStandard: {
  '&:hover': {
    backgroundColor: 'rgba(0, 0, 0, 0.08)'
  }
},
pageNaviArrow: {
  '&:hover': {
    backgroundColor: 'rgba(0, 0, 0, 0.08)'
  }
}
```

```javascript
const { userList, parPage, offset } = this.state

{userList.length > parPage && (
  <Pagination
    limit={parPage}
    offset={offset}
    total={userList.length}
    onClick={(e, offset) => this.handleClickPagination(offset)}
    className={classes.pageNav}
    classes={{
      rootStandard: classes.pageNaviStandard,
      rootCurrent: classes.pageNaviCurrent,
      rootEnd: classes.pageNaviArrow,
      text: classes.pageNaviText
    }}
  />
)}
```

ボタンっぽくしたかったのでborderつけたり、width、height指定したりたりしています。

###3.ループさせた時のイベント処理

ループさせている各リストごとに、例えば「編集」や「削除」ボタンがあって操作させる時、順番を取ることがあると思います。

例）

```javascript
<ul>
  {this.state.userList
    .slice(offset, offset + parPage)
    .map((user, i) => {
      <li>
        {user.id}: {user.name}
        <Button
          onClick={e => this.handleClickEdit(i, e)}
        >
          編集
        </Button>
        <Button
          onClick={e => this.handleClickRemove(i, e)}
        >
          削除
        </Button>
      </li>
    })
  }
</ul>
```

`offset`は、２ページ目以降の`index`は現在表示されているリストの上から何番目かを取得しています。
取得した全データをローカルステートに入れていると、ページ送りした分＋ページ上から数えて何個目かを指定する必要があります。`offset`は「nページ目 × 1ページに表示させる個数」なので、indexは下のように取得できます。

```javascript
handleClickEdit = (i, e) => {
  const users = this.state.userList
  const index = this.state.offset + i

  users[index].name = e.target.value
  this.setState({
    userList: users
  })
}
```

簡単です！

##終わりに
Material-UIデフォルトでこのページネーションがあれば良いのにと思いましたが、material-ui-flat-paginationを使って簡単に実装できたので、とても有効的だと思いました。