Reactで綺麗なページネーションを簡単に実装する方法【material-ui】
webアプリを作っていると多くの場面で必要になるのがページネーションです。googleやamazonにも実装されています。
Reactにおいてページネーションを使うにはmaterial-uiが便利なのでこの記事にまとめておきます。
この記事で作成するページネーション
material-uiのページネーションを使う
まずは、material-uiのパッケージの取り込みが必要です。
yarn add @material-ui/lab
通常のmateril-uiのコンポーネントを取り込む際のパッケージと異なるので注意してください。
material-ui/labとは?
material-ui/lab
とは、まだmaterial-ui/core
に取り込むべきでないライブラリーが入ったものです。
通常、material-uiを使う場合はyarn add @material-ui/core
でcoreを取り込む必要があります。しかし、そのcoreの中にバグが含まれているとバージョンアップするのに時間がかかる。
このような事態に備えて使用頻度が低いものや、コードの質が低いものはlabに分けて登録しているのです。
ページネーションを使う
それでは実際にmaterial-uiのページネーションを使っていきます。
import MuiPagination from '@material-ui/lab/Pagination';
import { withStyles } from '@material-ui/core/styles';
import {useState} from 'react'
export default function Index() {
//ページ番号
const [page, setPage] = useState(1)
const Pagination = withStyles({
root: {
display: 'inline-block', //中央寄せのためインラインブロックに変更
},
})(MuiPagination);
return (
<div style={{textAlign: "center"}}>
<Pagination
count={10} //総ページ数
color="primary" //ページネーションの色
onChange={(e, page) =>setPage(page)} //変更されたときに走る関数。第2引数にページ番号が入る
page={page} //現在のページ番号
/>
</div>
);
}
上記のソースのようにPagination
モジュールを取り込み、必要な属性を設定して使用します。また、クリックされたページ番号をonChange
で変更し、対象の番号をアクティブにしています。
ちなみに、よく使う属性の一覧は以下のようになっています。
-
boundaryCount
:最初と最後に表示するページ数 -
count
:総ページ数 -
page
:現在のページ番号 -
siblingCount
:現在のページ前後に表示するページ数
ページャーを中央寄せするには?
ページャーを中央寄せするには、root
である.MuiPagination-root
クラスにdisplay:inline-block
を適用し、親要素にtext-align:center
を追記する必要があります。
ページャーのトップのnav要素はデフォルトだとdisplay:block
が適用されるためtext-align:center
が効きません。そのため、inline-block
に変更してtext-align:center
が効くことで中央寄せが可能になります。
ページネーションのHTML
<nav aria-label="pagination navigation" class="MuiPagination-root WithStyles(ForwardRef(Pagination))-root-20">
<ul class="MuiPagination-ul">
<li><button class="MuiButtonBase-root MuiPaginationItem-root MuiPaginationItem-page MuiPaginationItem-textPrimary" tabindex="0" type="button" aria-label="Go to previous page"><svg class="MuiSvgIcon-root MuiPaginationItem-icon" focusable="false" viewBox="0 0 24 24" aria-hidden="true"><path d="M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z"></path></svg><span class="MuiTouchRipple-root"></span></button></li>
<li><button class="MuiButtonBase-root MuiPaginationItem-root MuiPaginationItem-page MuiPaginationItem-textPrimary" tabindex="0" type="button" aria-label="Go to page 1">1<span class="MuiTouchRipple-root"></span></button></li>
<li>
<div class="MuiPaginationItem-root MuiPaginationItem-ellipsis">…</div>
</li>
<li><button class="MuiButtonBase-root MuiPaginationItem-root MuiPaginationItem-page MuiPaginationItem-textPrimary" tabindex="0" type="button" aria-label="Go to page 5">5<span class="MuiTouchRipple-root"></span></button></li>
<li><button class="MuiButtonBase-root MuiPaginationItem-root MuiPaginationItem-page MuiPaginationItem-textPrimary Mui-selected" tabindex="0" type="button" aria-current="true" aria-label="page 6">6<span class="MuiTouchRipple-root"></span></button></li>
<li><button class="MuiButtonBase-root MuiPaginationItem-root MuiPaginationItem-page MuiPaginationItem-textPrimary" tabindex="0" type="button" aria-label="Go to page 7">7<span class="MuiTouchRipple-root"></span></button></li>
<li>
<div class="MuiPaginationItem-root MuiPaginationItem-ellipsis">…</div>
</li>
<li><button class="MuiButtonBase-root MuiPaginationItem-root MuiPaginationItem-page MuiPaginationItem-textPrimary" tabindex="0" type="button" aria-label="Go to page 10">10<span class="MuiTouchRipple-root"></span></button></li>
<li><button class="MuiButtonBase-root MuiPaginationItem-root MuiPaginationItem-page MuiPaginationItem-textPrimary" tabindex="0" type="button" aria-label="Go to next page"><svg class="MuiSvgIcon-root MuiPaginationItem-icon" focusable="false" viewBox="0 0 24 24" aria-hidden="true"><path d="M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"></path></svg><span class="MuiTouchRipple-root"></span></button></li>
</ul>
</nav>
ブロック要素のtext-align:center
display:block
は通常、要素が縦方向に並ぶようになっています。しかし、今回の場合は横方向に並んで見えているのはnav配下のulにdisplay: flex;
を適用しているためです。これにより横方向に並んでいるように見えます。nav属性自体は縦方向に1行で表示させています。
そのため、以下のようにブロック要素のpタグの親要素にtext-align:center;
を追記していも中央寄せになりません。(ただし、pタグ内のテキストは中央寄せされる)
<div style="width: 500px; text-align:center; background-color: blue;">
<p style="width: 100px; background-color: skyblue;display:block;">
aaa
</p>
</div>
インラインブロック要素のtext-align:center
一方、display:inline-block
は横方向に並べる表示方法で、こちらはtext-align:center
による中央寄せが効きます。ただし、親要素に追記が必要なことは注意が必要です。
<div style="width: 500px; text-align:center; background-color: blue;">
<p style="width: 100px; background-color: skyblue; display:inline-block;">
aaa
</p>
</div>
まとめ
- material-uiのページネーションを使うには
@material-ui/lab
の取り込みが必要 - ページ番号をクリックするたびに変更して、アクティブなページを変える
- material-uiのページネーションはnav要素でできているため、中央寄せするにはrootに
display:inline-block
を設定し、親要素にtext-align:center;
が必要
Discussion
@mui/material
ライブラリから提供されているusePagination
フックを使ってデモを作ってみました。簡単ですが、以上です。