go_routerを使ってみた(単純な画面遷移の方法)


go_router というパッケージ、ご存知でしょうか。
Navigator 2.0 と呼ばれる宣言的な画面遷移を、簡単にするために作られたパッケージです。

https://gorouter.dev/

今回はこのgo_routerの紹介と、
単純な画面遷移にて、具体的な実装例を紹介します。

##go_routerの利点について##

個人的にいいな、と思うのは以下の3点です。

 1. 画面遷移のコードがめちゃくちゃ短く済む
 2. アドレスバーや戻るボタンを使った画面遷移に簡単に対応できる
 3. ドキュメントが日本語化されている

特に2.は普通にやろうとするとかなり複雑になってきます。
これらが簡単に実装できるのは、go_routerの強みだと思います。

3.のドキュメントが日本語化されていることも踏まえ、これから日本で流行っていく手法だと、
自分は考えています。

https://zenn.dev/inari_sushio/scraps/01ef7604a4b934

##go_routerの実装例##

例として、ログイン画面から本のリスト画面へと遷移する、単純な画面遷移のコードで紹介します。

サンプルコードはこちらに用意しています。
ぜひ合わせてご確認ください。

https://github.com/Umigishi-Aoi/go_router_sample/tree/master/go_router_sample

###パッケージのインポート###

pubspec.yamlに以下のコードを追加し、パッケージをインストールします。

```yaml:pubspec.yaml
dependencies:
  go_router: ^3.0.1
```

（バージョンは以下のページを参照して最新のものに合わせてください。）

https://pub.dev/packages/go_router/install

###画面の定義###

go_routerでは遷移する画面をあらかじめ定義しておく必要があります。

``MaterualApp``を使用するクラスにて、``GoRouter``クラスのインスタンスを定義します。

```dart:main.dart
//画面の情報を定義する
  final _router = GoRouter(
    //1
    initialLocation: '/',
    //2
    routes: [
      //3
      GoRoute(
        //4
        name: 'login',
        //5
        path: '/',
        //6
        pageBuilder: (context, state) => MaterialPage(
          //7
          key: state.pageKey,
          ///8
          child: const LogInPage(),
        ),
      ),
      //9
      GoRoute(
        name: 'list',
        path: '/list',
        pageBuilder: (context, state) => MaterialPage(
          key: state.pageKey,
          child: const BookListPage(),
        ),
      ),
    ],
    //10
    //遷移ページがないなどのエラーが発生した時に、このページに行く
    errorPageBuilder: (context, state) => MaterialPage(
      key: state.pageKey,
      child: Scaffold(
        body: Center(
          child: Text(state.error.toString()),
        ),
      ),
    ),
  );
```

//1 
アプリを立ち上げた時に最初に表示されるページのパスを定義します。
(パスについては後述)
//2
ここに定義したものが画面として定義されます。
//3
go_routerでは画面を``GoRoute``で定義します。
//4
画面につける名前です。画面遷移時に使用します。(後述)
//5
画面のパスを定義します。ここで定義した名前がアドレスバーに表示されます。
//6
このパスにアクセスされた際のページの生成を定義します。
``BuildContext``と``GoRouterState``を引数に持ちます。返り値は``Page``です。
//7
キーを定義します。``state.pageKey``でキーが自動生成されます。
//8
実際に表示する画面のクラスを宣言します。
(今回は``LogInPage``)
//9
定義内容は上の繰り返しとなります。
上で定義したものと異なるパス、名前をつけます。
//10
``route``で定義したもので対応していないパスを入力された時など、
エラーが発生したときに表示する画面を定義します。

##MaterialAppへのGoRouterインスタンスの追加##
``MaterialApp``を``MaterialApp.router``に変更し、
上記で定義した``GoRouter``インスタンスを使用して、
プロパティに定義します。

```dart:main.dart

@override
  Widget build(BuildContext context) {
    //11
    return MaterialApp.router(
      //12
      routerDelegate: _router.routerDelegate,
      routeInformationParser: _router.routeInformationParser,
      title: 'Book List Sample',
    );
  }

```

//11
``MaterialApp.router``で定義します。
//12
``routerDelegate``と``routeInformationParser``を``GoRouter``インスタンスのフィールドで定義します。
``GoRouter``のインスタンスを定義すれば、自動でこれら２つを作成してくれるわけです。
これを自作で作ろうとするとかなり面倒でした。
ここが、go_routerのポイントだと個人的に思っています。

ここまでできれば、アプリを立ち上げた際、
``initialLocation``で定義したパスのページが開かれます。

##画面遷移の方法##
以下のコードにて画面が遷移されます。

```dart
GoRouter.of(context).go(パス);
```

上の例でいうと、以下のようになります

```dart
GoRouter.of(context).go('/list');
```

この書き方には短縮系があり、以下のようにしても画面遷移可能です。

```dart:
context.go('/list');
```

また、上で定義した、画面の名前を使って以下のようにしても画面遷移可能です。

```dart:
context.goName('list');
```

かなり短く書けますよね。
これは、go_routerの利点だと思います。

以上で画面遷移の説明は終わりです。
サンプルコードにて、

- アドレスバーにパスが表示されていること
- ログインボタンを押すと、画面が遷移すること
- 戻るボタンを押してログイン画面に遷移すること
- アドレスバーに直接パスを打ち込んで遷移すること

を確かめてみてください。

##まとめ##

今回はgo_routerの紹介と、基本的な使い方の紹介を行いました。
便利なgo_routerですが、
画面間で情報の受け渡しをしようとすると状態管理手法が必要になってきたりと、少し複雑になります。
また、別記事で紹介できればと思います。

ぜひ、導入を検討してみてください。

https://www.youtube.com/watch?v=G41NdhieUoc&list=TLGGKAy3IFGg_1YyMTAxMjAyMg&t=6s