はじめに
今回から複数回に分けて、MUI が提供している usePagination というカスタムフックをコードリーディングします。
一覧画面を作るとき、ページ送りするためのUIをページャ(またはページネーション)といいます。
ですがこのページャは、自分で作ろうと思うとなかなかやっかいなものです。
例えば、表示するページが3ページのとき、1〜3のボタンを表示してあげるだけなので簡単です。
しかし、表示するページが30ページのときはそうも言ってられません。
1から30までボタンを全部出したら見づらいのなんの。。。
使い勝手も悪いし、見た目もよくありません。
ページ数が多いときは、程よく省略表示してあげないといけません。
でもここで問題となるのは「それ、どうやって作るの?」ということですよね。
一から処理を考えて自分で作ってみるのもいいでしょう。
しかし、ページャのようなよくあるUIは、これまでたくさんの先人たちによって作られてきたはずです。
それを使わせてもらったほうが、バグもなくて省エネな実装ができるはずです。
概要
以下のリンクは、いい感じのUIを提供してくれる MUI というライブラリの Pagination コンポーネントです。
デモ画面では10ページ表示になっていますね。
デモ画面を少し操作してみましょう。
例えば、5ページ目を表示したとき 2〜3ページ目、7〜9ページ目が省略表示されます。
7ページ目を表示したとき、2〜5ページ目が省略表示されます。
このように、表示中のページによっては省略する箇所が1つだったり、2つだったりします。
さらに、省略するページの数も2ページ分だったり4ページ分だったりと変動します。
これがページャの難しいところです。
MUI では、この表示の制御処理が usePagination というカスタムフックにまとめられています。
今回は、usePagination の制御処理をコードリーディングしてみましょう。
usePagination のロジックを読む
今回コードリーディングするソースはこちらです。
props からフックの使い方を想像する
usePagination は引数 props
を受け取ります。
この props
の中身をみることで、どんなことができそうか想像できることがあります。
「こんなことできそうだな〜」となんとなくでもイメージしておくと、コードリーディングの助けになったりするのでおすすめです。
export default function usePagination(props = {}) {
// keep default values in sync with @default tags in Pagination.propTypes
const {
boundaryCount = 1,
componentName = 'usePagination',
count = 1,
defaultPage = 1,
disabled = false,
hideNextButton = false,
hidePrevButton = false,
onChange: handleChange,
page: pageProp,
showFirstButton = false,
showLastButton = false,
siblingCount = 1,
...other
} = props;
私がこれを読んで想像したのは以下でした。
このくらいでも全然オッケーですよ。
boundaryCount
boundary=境界だから、何かしらの境界値だろう。「…」で省略表示するのに関係してるのかな?count
まぁ、たぶん検索結果の総件数だよねhideNextButton
hidePrevButton
へ〜、矢印ボタン(<
>
)が隠せるんだpage
現在ページのことだよねsiblingCount
sibling? 翻訳したら「兄弟」。なんだこれ?
戻り値を見て、最終的に何を返しているのかを把握する
フックは基本的に何かしら値を返します(useEffect
のように使う場合は戻り値はないですが)。
その返している値を見ることでも、どんなことをしているのか想像することができます。
// Convert the basic item list to PaginationItem props objects
const items = itemList.map((item) => {
return typeof item === 'number'
? {
onClick: (event) => {
handleClick(event, item);
},
type: 'page',
page: item,
selected: item === page,
disabled,
'aria-current': item === page ? 'true' : undefined,
}
: {
onClick: (event) => {
handleClick(event, buttonPage(item));
},
type: item,
page: buttonPage(item),
selected: false,
disabled:
disabled ||
(item.indexOf('ellipsis') === -1 &&
(item === 'next' || item === 'last' ? page >= count : page <= 1)),
};
});
return {
items,
...other,
};
items
とその他いろいろを返していますね。
今回は少し上をみたら items
が何なのかがわかりました。
itemList
を map
して、何か新しく配列を作っています。
中身を見てみると、onClick
やら selected
やら buttonPage(item)
を持ったオブジェクトです。
ページャのボタン(1、2、3・・・)のオブジェクトを返しているように思います。
このように、入力(props)と出力(戻り値)をみることで、usePagination フックはなんとなく以下のようなことをしているのだと想像できました。
ページ数や現在ページを渡せば、ページャのボタン(1、2、3・・・)のオブジェクトの配列を返してくれる。
boundary とか sibling とかちょっと何言っているかわからないものもあるけど、hideNextButton とかでカスタマイズもできそう。
「ページャを表示するためのフックなんだから当たり前だろ!」というツッコミが聞こえてきそうですね笑
でも、こうやって何となくでもあらかじめ想像しておくことで、コードリーディングしやすくなったりします。
ぜひ試してみてください。
おわりに
いかがだったでしょうか?
今回は MUI のページャを表示するためのフック usePagination を読んで、どんなことをしているのかを少し想像してみました。
次回は、この usePagination フックを使ってみて、どんな値が返ってくるのかを調べてみましょう。
コメント