はじめに
少し前から気になっていた React のルーティングライブラリである React Location を使ってみた。React Location にはどのような特徴があるのか、また React Router との違いなどについても書いていく。
補足
2022 年 11 月に React Location は TanStack Router という名前に変更されました。API にも大幅な変更が発生しています。このセクション以降の内容は無となりましたので、注意してください。
実験のために作ったものは TanStack Router に置き換えていきます。興味のある方は参考にしてください。
環境
- Library: React 18.x
- Routing: React Location 3.x
- State management: Jotai 1.x
- Building: Vite 2.x
- Testing: Vitest 0.16.x
- Hosting: Cloudflare Pages
作ったもの
上記の環境で以下を作った。
Experinica は自分が以前作った jamband/tapes のコピー品のようなものである。jamband/tapes は本番環境にビルド・デプロイすると、各 route はそれに対応する HTML とデータファイルを生成する。詳細は以下で確認できる。
Experinica では jamband/tapes で生成されたデータファイルを Fetch API を用いてリクエストしデータを取得する。スタイルなどはほぼ jamband/tapes に合わせているため、結果的に見た目は同じようなものになる。ただ jamband/tapes は SvelteKit を使った静的サイト + SPA のようなものであるのに対して、Experinica は完全なる SPA であることに注意する。
React Location の特徴
React Location は React のルーティングライブラリである。アプリケーションの各 route を配列オブジェクトで構成する。以下のような感じ:
あとは Router プロバイダーコンポーネントの props に構成した routes を読み込ませる:
開発サーバを立ち上げて Web ブラウザで以下にアクセスする (ポート番号は任意):
http://localhost:3000
// home... と表示されるか確認する
http://localhost:3000/foo
// foo... と表示されるか確認する
基本はこんな感じ。
では React Router と比較した場合、React Location には他にどのような機能があるのかを見ていく。
1 つ目は Route Loaders 。各 route はだいたいの場合 API サーバからデータを取得するよね?それらの実装は loader プロパティを使って非同期な関数で書けるよ、といった感じ。
たとえば /(ホーム) route に対していくつかのデータを API サーバから取得したい場合は以下:
Home コンポーネントでは useMatch フックをつかってデータを取得する:
特徴的なのは、すべてのデータを取得後に DOM をレンダリングするところ。なので、ローディングスピナー地獄であったり、一瞬レイアウトが崩れてしまったり、画面がちらついたり、といったことを気にしなくていい。
データの型は MakeGenerics を使って書く:
2 つ目は、現状 Server-Side Rendering (SSR) をサポートしていないところ。そのため使い所は限定される。個人的には React Location の書き心地が良いので、SSR をサポートしつつ、どこかのフレームワーク内部で使われたら最高なのに… とか浅い感想を持っているが、React 18 以降のことであったり、React Router との違いを考えると、今後どうなるかは不明。
3 つ目は、Search Params 。これは Route の Path や Path Params では表現できないより細かな制御を必要とするときに使う。複数の状態を URL の query string に持たせて特定のデータを検索したい場合など、つまり管理画面などではよく使われそうな機能。
その他の細かな比較に関しては Comparison | React Location vs React Router が参考になる。
Route 間の移動について
Link コンポーネントを使うことによって route 間を移動できる。
また、useNavigate フックを使用することによってプログラムよるナビゲーションができる。
Route Loaders のキャッシュについて
React Location には Route Loaders のキャッシュを制御するために React Location Simple Cache というパッケージが用意されている。簡易的なキャッシュについてはこれを使う。管理画面のようなより複雑なものに対しては React Query のほうがより制御しやすいかもしれない。
ちなみに Experinica では React Location Simple Cache を使っている。ローディングを表現するスピナーが表示される場合は API サーバにリクエストしている状態であり、一度リクエストしたものは JavaScript のメモリにキャッシュされ、再度同じルートに移動した場合はそのキャッシュが使われスピナーは表示されない。
ただ、これはあくまで JavaScript のメモリによるキャッシュであるため、Web ブラウザをリロードすると破棄される。
コンポーネントのテストについて
特定のコンポーネントが React Location のなにかしらに依存していて、そのままではテストが行えない場合は、デフォルトの Browser Routing から Memory Routing に切り替えてテストを行う。
例えば以下のようなコンポーネントがあった場合:
以下のようにテストを書くことができる:
まとめ
この記事を書いているちょっと前に React のバージョン 18 がリリースされた。周辺のライブラリも React 18 のサポートを進めている。
そんな中でこの記事を書いていて、ちょっとタイミングが悪いなと思いつつ、それでも改めて感じたのは、今回使った React Location やその他の TanStack のライブラリも含め、 やっぱ React って周辺のライブラリも含めてほんと充実していて、質が高いものが多いなぁと。
また、今回初めて試しに使ってみた状態管理ライブラリである Jotai も非常に使いやすかったし、またどこかで使ってみたい。
関連リンク