react-gridsheetがさらにおいしくなりました。

公開:2021/02/23
更新:2021/02/23
3 min読了の目安(約3300字TECH技術記事

といって内容量が減るお菓子のような話も一部含みます😇

react-gridsheetのパフォーマンス改善とそれに伴う機能追加などを行いました。
具体的には前回の記事でご紹介した react-window を導入しました🐰

前回の記事:

https://zenn.dev/righ/articles/3163e6671851d5

大量データの表示

ウィンドウィングによりシート外の要素描画が行われなくなり、パフォーマンスは大幅に改善しました。Exampleも2つ追加されています。他の例も見たい方は是非リンク先をご覧ください🙏

(行、列単位のリサイズも出来ますが、codesandbox上だとうまく機能しないようです)

256x256=65536セルのデータがありますが、ラグもなく操作できています。感動ですねこれは🥳

前回まで複数のシートを表示できないバグがありましたがこれも解消されています。
store の初期化をグローバルで行っていたことが原因だったので、コンポーネント内で行うようにしたら直りました👌

ペアワイズの組み合わせ生成

次の例はペアワイズの組み合わせを下のシートに出力します。特に変わったオプションを使っているわけではありませんがこういう使い方もできるということで...

ペアワイズのライブラリはこちら:

https://github.com/walkframe/covertable

さて、話がそれました👅
react-windowの副作用により変化した部分がいくつかあるので、以下ではそれらについて書いていきます。

シートサイズの指定

react-window の仕様で、縦横のサイズ指定が必須になりました👹
sheetHeight, sheetWidth props でこのサイズを渡すことができ、省略した場合は 縦が500px, 横が1000px となります。

今までは表示する要素分の領域を確保するだけでしたが、最新(0.4.x)バージョンからは要素が足りなくても指定した縦横サイズは領域として確保されます🙊
この仕様については微妙に思うかもしれませんが対応が煩雑になりそうなのでハンドリングはユーザに任せることにしました👻
具体的には「ヘッダ+セルサイズの合計を縦横それぞれ指定する」「初回表示で縦横サイズを超えるようにデータを指定する」などです。

とはいえ、style props を渡せるようにしたため、 style={{ maxWidth: "100%"}} とすることで1つ目のExampleのように親要素を超えないようにシートを描画できます。

また、これまでサイズの指定は 100px のように文字列で指定する仕様でしたが計算の都合で数値(px)に変更しました🤏

表構造

react-window には Listとよばれる1次元のデータを描画する機能とGrid とよばれる2次元のデータを描画する機能があり、当ライブラリでは両方とも利用しています🎃

https://react-window.now.sh/#/api/VariableSizeList

https://react-window.now.sh/#/api/VariableSizeGrid

Gridだけで十分のように思えますが、Gridはヘッダ部分を区別して表現することができません。そのため、「横向きのList」と「縦向きのList」を並べてスクロールを同期することでヘッダのように見せかけているわけですね。

https://github.com/walkframe/react-gridsheet/blob/v0.4.4/src/components/GridTable.tsx#L126-L129

能動的にスクロールする部分は Grid だけであり、ヘッダ部分はGridの外にあるのでヘッダとボディを同じようにスクロールすることができなくなりました。stickyの必要が薄れたため stickyHeaders オプションは一旦廃止です☄️
もちろん、画面上部に張り付く sticky と全く同じ挙動になるわけではないのですが、少し実装が大変なのでどうしても必要という人がいればそこで対応を検討します。

正式なリリースがあるまではこのように破壊的な変更が入ることもあると思います🐼
とはいえこれほど大きな変更はあまり多くはないはずです。

入力領域の変更

地味なのでわかりにくいと思いますが、以前は各セルに対して入力領域を用意していました。
ウィンドウィングによって選択中のセルが画面外に出るとフォーカスがはずれ入力が無効化されてしまう問題が生じたため、入力領域を一つにして、操作によって表示座標を移動する実装に変更しました。
これは意外と大変でしたが、入力した文字が残ってしまうバグも解消されたので悪いことばかりではなかったと思います🦧

検索機能の追加

前述したようにウィンドウィングにより表示領域外は要素自体が描画されなくなりました。
これによりブラウザのページ内検索ではヒットしなくなってしまうので独自の検索機能を追加する必要がでてきました🔍

Ctrl+F で検索ポップアップを表示し、ポップアップ内のテキストボックスに入力した文字列によりセルの絞り込みと該当要素までスクロールが行われます⛷また、テキストボックス内の Enter で次へ、Shift+Enter で前へ進みます。
スプレッドシートのようにボタンを用意したかったんですがアイコンを用意するのがめんどくさかったので雑対応ですw

入力した段階でセルの絞り込みが行われるので、入力した後でセルの内容を変更してもヒットしない仕様になっています。いつかバグとして報告されそうな雰囲気を感じます。許してください🥺

おわりに

以上が変更点です。
多少ネガティブな部分もありますが、致命的な問題は潰せたので普通に利用できそうな雰囲気になってきたと思います。(redux は果たして消せるのか...)

最近これに時間を使いすぎているので、ちょっとだけ放置するかもしれませんが Issue や PR は歓迎です。スターもモチベーションになるのでよろしくおねがいします⭐️

https://github.com/walkframe/react-gridsheet

そういえば、記事では codesandbox の埋め込みを頻繁に利用していますが、型解決が効かなくなる問題が再発したのでこれからは利用するのを控えていこうと思います。積極的に更新しないので最新のコードが見たい方はドキュメントの方のExampleをご覧ください🌳

https://docs.walkframe.com/products/react-gridsheet/examples/

PRを投げて解決したと思ったんですがバージョンアップしたらまた再発したので恒久的な対応が行われたわけではないようです。

https://github.com/codesandbox/codesandbox-client/issues/5452