GoRouter
プログラミング
GoRouterはFlutterのルーティング, ナビゲーションを便利するパッケージ
感想
新規に導入する分には使って良さそう、既存から移行もいけるだろうけどちょっと大変かも
pathがStringだけなのが地味に辛い、型付きルーティングを待つべきか悩ましい
refreshListenableはProvider/Riverpodとの相性が良さそう
Navigator2.0からの移行はページ遷移管理のControllerをGoRouterに書き換えが必要そう
目次: https://zenn.dev/inari_sushio/scraps/01ef7604a4b934
宣言的ルーティング
https://github.com/csells/go_router/blob/main/docs/ja/declarative-routing.mdx
パラメータの大文字小文字はそのままロケーション名に反映されますが、path との照合はケース・インセンシティブ(大文字小文字を区別しない)方式で行われます。
パラメータ限定の話?
path: '/hoge' != path: '/hOgE' であってほしい
pathに関して完全一致なはず、nameに関しては 'huga' == 'HUGA' になる
state.errorはExceptionが渡せるからエラーハンドリングに上手く使えそう
GoRouter(errorBuilder: があった。わざわざ別ページに飛ばすことあるかな?
ダイアログ出してpopが常套手段だと思っていた
Deep Linkの設定は新規開発だと忘れそう
https://docs.flutter.dev/development/ui/navigation/deep-linking
ナビゲーション
https://github.com/csells/go_router/blob/main/docs/ja/navigation.mdx
自動でファイル参照は入らないなかったので GoRouter.of(context).goを使うことになりそう
GoRouterで参照つける→GoRouter消す→context.go書くならインテリセンス効くけどcontext.go一発では入らなかった
goとpushの違い
'/'から'/go/to/page/'を例として、
go
goページ、toページ、pageページが順番にスタックされる
page
最後のpageページだけが/の下にスタックされる?
ディープリンクを使うとinitalLocationは無視される
GoRouterはChangeNotifier
extraはウェブアプリ向けでは非推奨
ブラウザの戻るで戻るとオブジェクトが消えるらしい
サブルート
https://github.com/csells/go_router/blob/main/docs/ja/sub-routes.mdx
routesでWidgetのchildスタックみたいなことができる
サンプルがFamiliesでRiverpodと被るなあと思ったけど予約語じゃなかった。Familyデータがあるという仮定の話だった
リダイレクト
https://github.com/csells/go_router/blob/main/docs/ja/redirection.mdx
code:dart
// ユーザーがログインしていない場合はログインページにリダイレクト
redirect: (state) {
final loggedIn = loginInfo.loggedIn;
final goingToLogin = state.location == '/login';
// ユーザーがログインしておらず、かつ /login に向かっていない場合はログインが必要
if (!loggedIn && !goingToLogin) return '/login';
// ユーザーがログイン済みで、かつ /login に向かっている場合はログイン不要
if (loggedIn && goingToLogin) return '/';
// 一切リダイレクトが不要な場合
return null;
},
ログインしていなかったらログインページにリダイレクトは便利そう
これなしだとページのあちこちでログインしているかを判定する必要があって、だぶり・もれが出てしまう
code:dart
GoRouter(
...
// listenable に変化があればルータによってルートがリフレッシュされる
refreshListenable: loginInfo,
loginInfoが変わるとGoRouterのリダイレクト判定が走るらしい
これも使いそう。そして忘れそう
ProviderでいけるならRiverpodでも指定できるはず
GoRouterRefreshStreamでラップすることでstream も渡すことができるみたい
BLoCが例に挙げられていたし使うことはないかも?
code:dart
onPressed: () {
// ユーザーをログインさせてリスナーに通知
context.read<LoginInfo>().login('test-user');
// loginInfo があるので、/login から / へルータが自動的にリダイレクト
//context.go('/');
},
↑良すぎる。コードもスッキリだし遷移に関するコードがRouteにまとまっているのがみやすくてとても良い
redirectの呼び出しについて
redirectがない
builderが必要
redirectがnullを返す可能性がある
builderも必要
redirectが必ずString
builderは不要 (トップレベル以外でredirect書くと無視される)
redirectLimitが指定されている (デフォルト 5)
連続したリダイレクトはバグの可能性が高いため
redirectループに注意
詳細は読者の演習とする
an exercise that I'll leave to the reader
久しぶりにこの言い回し見た
loginFromもstateに渡せるからログ取りにも使えそう
名前付きルート
https://github.com/csells/go_router/blob/main/docs/ja/named-routes.mdx
pathだけでなくnameも指定できる
nameにenumなりFreezedなりのtoStringを渡せばハードコーディングなしでいけそう
パラメータ、リダイレクトも可能
URLパス・ストラテジー
https://github.com/csells/go_router/blob/main/docs/ja/url-path-strategy.mdx
webとしてデプロイする時の話
デフォルトだとURLに#がつくけどGoRouterだと簡単に外せる
URLがindex.htmlに紐づくようにしないとルーティングできないらしい (あまり内容がわからず)
ルートのデバッグ
https://github.com/csells/go_router/blob/main/docs/ja/debugging.mdx
code:dart
debugLogDiagnostics: true,
ルーティング中の情報を出力してくれる
いつかお世話になる時が来るかもしれない
トランジション効果
https://github.com/csells/go_router/blob/main/docs/ja/transitions.mdx
builder, errorBuilderの代わりにpageBuilder, errorPageBuilderを使うとHogeTransitionPageでPageをラップして遷移効果を付与できる
この辺りはNavigator1.0と同様な感じがする
NoTransitionPageのようによく使うCustomTranstionはクラスとして作ることができる?
できるであればボイラプレートになってしまうから作りたい
Transtionのkeyを同じにすることで同じkey間の遷移には効果が付かないようにできる
タブ移動のページとかで、タブ遷移の効果がつくからTransition効果はpush,popの時だけ欲しいときに使える
非同期データ
https://github.com/csells/go_router/blob/main/docs/ja/async-data.mdx
idを渡して遷移先のページで取得する
Riverpodとかでもやっている手法
パラメータの使い方でGoRouterが何かサポートしているわけではなさそう
ネストナビゲーション
https://github.com/csells/go_router/blob/main/docs/ja/nested-navigation.mdx
タブとかの画面ない遷移でlocationも変わる
ディープリンクが可能になる
URLをenumでやるには辛いだろうからやはりFreezedか
StateFulWidgetにしてAutomaticKeepAliveClientMixinをつけようね
Web以外だと使う場面が限られてくるかも(Riverpodで代替できそう)
Navigatorビルダー
https://github.com/csells/go_router/blob/main/docs/ja/navigator-builder.mdx
navigatorBuilder:でMaterialAppとNavigatorの間(よくProviderを置く層)にWidgetをおける
複数ページに適用できるオーバーレイとしても機能できる
Navigatorとの併用
https://github.com/csells/go_router/blob/main/docs/ja/navigator-integration.mdx
Navigator.push, Navigator.popが動作する
Navigator.pushだとアドレス更新ができない(Web)
GoRouterで代替できる
新規画面を呼び出す側がナビゲーションの結果を受け取ることができないのであれば、新規画面側でユーザーによる入力を処理すればいいのです
確かに
新規登録の場面に限らず、この発想の転換は活かせる場所がありそう
一緒に使ってはいけない場面はないけど、状態管理とリビルドに気をつけて使う
ウェブ履歴
https://github.com/csells/go_router/blob/main/docs/ja/web-history.mdx
Router.reglectでブラウザに履歴を残さずに遷移できる
GoRouter(routerNeglect: true,.. でアプリ全体で残さないようにもできる
ブラウザの戻るボタンには影響する
多分履歴がのこっているひとつ前に戻る?
型付けルーティングの提案
https://github.com/csells/go_router/blob/main/docs/ja/typed-routing.mdx
まだWIP
name: 'family' から pushFamily, goFamilyメソッドが自動生成されるもの
context.go('familyyyy') とかで実行時エラーにならなくなるからとても良い
コード生成は初めは build_runner, マクロが来たら移行する
build_runnerなどのコード生成はオプションになる予定 https://github.com/csells/go_router/issues/66#issuecomment-975007176