URLを移動しても、React-Tableで今見ていたページ数を覚えておく

React-TableというReactのテーブル・コンポーネントがある。 以下のような特徴がある。

1. ヘッダー、セル、フッターの細部までカスタマイズ可能
2. デフォルトですでに多機能(フィルタリング、ソート、行数の変更、リサイズなど)
3. ドキュメントが丁寧

個人的なWeb開発に利用しているのだが、結局テーブルはこのコンポーネント一つで事足りた。 他のテーブルは使っていないので、比較はできないが、 本当にありがたいコンポーネントだった。 ごっつぁんでした。

ちなみに、Nozzle.ioという会社の共同創業者が書いたらしい。 なぜ、この人がReact-Tableを書いたのか、その熱い思いはここに書かれている。

困ったこと

明瞭なインターフェースと分かりやすいドキュメントでほとんど困ることはなかったのだが、一つだけ詰まったのが「いかにして、違うURLに移動しても、今見ていたテーブルのページ数を覚えておくか」ということだった。 移動前のページ数を覚えておかないと、例えば「テーブルの2ページ目を開いている時に違うURLに移動し、そのURLから戻ってきた時にテーブルが1ページ目になってしまっている」という問題が起きる。 言い換えると、違うURLから戻るボタンで戻ってきて、テーブルの続きを見ようかなと思っていると、1ページ目が表示されていて、肩透かしを食らってしまうというわけである。

この問題を解決するために、以下のようなコードを書いた。

class Table extends React.Component {

    constructor (props) {
        super(props)
        if (typeof window !== "undefined") {
            let stringAfterQuestion = window.location.href.match(/page=.*/, "")
            if (stringAfterQuestion === null) {
                this.state = {
                    tablePage: 0
                }
            }
            else {
                this.state = {
                    tablePage: Number(stringAfterQuestion[0].replace(/page=/, "")) - 1
                }
            }
        }
    }

    render () {
        //GatsbyのURLを変更するメソッド
        const navigateTo = require("gatsby-link").navigateTo
        return (
            <ReactTable
               className="-striped -highlight"
               data={tableData}
               columns={tableColumns}
               loading={this.props.loading}
               page={this.state.tablePage}
               pageSizeOptions={[20]}
               defaultPageSize={20}
               onPageChange={(pageIndex) => {
                   if (typeof window !== "undefined") {
                       this.setState({tablePage: pageIndex})
                       navigateTo(window.location.pathname + '?page=' + String(pageIndex + 1))
                       window.scrollTo(0, this.props.scrollPosition)
                   }
              }}
              />
        )
    }
}


基本的には、テーブルのページ数をstatetablePageで管理して、ReactTableのpageプロパティからそれを参照するという仕組みになっている。 プログラムの流れとしては、以下のようになる。

1. ページャーがクリックされたら、onPageChangetablePageを書き換える。
2. tablePageが書き換えられ、描画処理が始まる。
3. <ReactTable>pageプロパティにtablePageの値を代入し、そのページを表示させる。

ただ、これだけだと、他のURLから戻るボタンで戻ってきたケースでは、tablePageの初期値である0がpageに代入され、テーブルの1ページ目が描画されてしまう。 そこで以下のようなプログラムを付け加える。

1. ページャーがクリックされたら、onPageChange内でURLに?page=2といったクエリパラメータを付け加える、またはそれを書き換える。
2. ページの初期読み込みの際は、クエリパラメータとして保存した値をtablePageの初期値とする。

こうすることで、例えば、テーブルの2ページ目を見ていて、他のURLに移動し、また戻るボタンで戻ってきても、コンポーネントの初期化の際にURLの?page=2に保存された2がtablePageに代入され、移動前に見ていたテーブルの2ページ目が描画される。

もしかすると、「親コンポーネントのstateでテーブルのページを管理する」というやり方でもいけるのかもしれないが、 自分が試した時はページャーをクリックしてもテーブルのページ移動がされないというトラブルが生じた。