MUIの usePagination のロジックを読む1

目次

はじめに

今回から複数回に分けて、MUI が提供している usePagination というカスタムフックをコードリーディングします。

一覧画面を作るとき、ページ送りするためのUIをページャ(またはページネーション)といいます。
ですがこのページャは、自分で作ろうと思うとなかなかやっかいなものです。

例えば、表示するページが3ページのとき、1〜3のボタンを表示してあげるだけなので簡単です。

しかし、表示するページが30ページのときはそうも言ってられません。
1から30までボタンを全部出したら見づらいのなんの。。。

使い勝手も悪いし、見た目もよくありません。
ページ数が多いときは、程よく省略表示してあげないといけません。

でもここで問題となるのは「それ、どうやって作るの?」ということですよね。

一から処理を考えて自分で作ってみるのもいいでしょう。
しかし、ページャのようなよくあるUIは、これまでたくさんの先人たちによって作られてきたはずです。

それを使わせてもらったほうが、バグもなくて省エネな実装ができるはずです。

概要

以下のリンクは、いい感じのUIを提供してくれる MUI というライブラリの Pagination コンポーネントです。

あわせて読みたい
React Pagination component - Material UI The Pagination component enables the user to select a specific page from a range of pages.

デモ画面では10ページ表示になっていますね。

デモ画面を少し操作してみましょう。
例えば、5ページ目を表示したとき 2〜3ページ目、7〜9ページ目が省略表示されます。
7ページ目を表示したとき、2〜5ページ目が省略表示されます。

このように、表示中のページによっては省略する箇所が1つだったり、2つだったりします。
さらに、省略するページの数も2ページ分だったり4ページ分だったりと変動します。

これがページャの難しいところです。

MUI では、この表示の制御処理が usePagination というカスタムフックにまとめられています。
今回は、usePagination の制御処理をコードリーディングしてみましょう。

usePagination のロジックを読む

今回コードリーディングするソースはこちらです。

GitHub
material-ui/packages/mui-material/src/usePagination/usePagination.js at master · mui/material-ui Material UI: Comprehensive React component library that implements Google's Material Design. Free forever. - mui/material-ui

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 が何なのかがわかりました。

itemListmap して、何か新しく配列を作っています。

中身を見てみると、onClick やら selected やら buttonPage(item) を持ったオブジェクトです。
ページャのボタン(1、2、3・・・)のオブジェクトを返しているように思います。

このように、入力(props)と出力(戻り値)をみることで、usePagination フックはなんとなく以下のようなことをしているのだと想像できました。

ページ数や現在ページを渡せば、ページャのボタン(1、2、3・・・)のオブジェクトの配列を返してくれる。
boundary とか sibling とかちょっと何言っているかわからないものもあるけど、hideNextButton とかでカスタマイズもできそう。

「ページャを表示するためのフックなんだから当たり前だろ!」というツッコミが聞こえてきそうですね笑

でも、こうやって何となくでもあらかじめ想像しておくことで、コードリーディングしやすくなったりします。
ぜひ試してみてください。

おわりに

いかがだったでしょうか?

今回は MUI のページャを表示するためのフック usePagination を読んで、どんなことをしているのかを少し想像してみました。

次回は、この usePagination フックを使ってみて、どんな値が返ってくるのかを調べてみましょう。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

28歳のときに音楽家からエンジニアに転向。
WEB系のシステム開発(Java, C#, Vue, React など)に携わっています。

自分らしく力を発揮できて、自信を持って生きられる人を増やすための活動をしています。

コメント

コメントする

目次