とんかつ時々あんどーなつ

〜たとえ低空でも飛行していられるように〜

Angular v18 で Route.redirectTo に関数を指定する

Angular v18 で Route.redirectTo に関数が渡せるようになったため、それを試した記事である。

はじめに

Route.redirectTo とは、ルーティングの際にパスがマッチしたらリダイレクトするパスを指定するためのプロパティとして提供されていた。 v18 で Route.redirectTo に指定できる型が string に加え、関数が追加されたため、今回はその動きを確認する。

redirectTo に関数を指定

関数が指定できるとはどういうことか?今までは次のように redirectTo に string を指定していた。

// app.routes.ts

export const routes: Routes = [
  { path: '', redirectTo: 'home', pathMatch: 'full' },
  { path: 'home', component: HomeComponent },
];

これを以下のように書くことができるようになる。

// app.routes.ts

export const routes: Routes = [
  {
    path: '',
    redirectTo: () => {
      return 'hello';
    },
    pathMatch: 'full',
  },
  { path: 'home', component: HomeComponent },
];

公式ドキュメント を見ると redirectTo に渡せる関数の型は RedirectFunction となっている。 型指定をすれば、名前をつけて切り出しておくこともできる。

// app.routes.ts

const redirectToFn: RedirectFunction = () => {
  return 'hello';
};

export const routes: Routes = [
  { path: '', redirectTo: redirectToFn, pathMatch: 'full' },
  { path: 'home', component: HomeComponent },
];

関数が渡せるということは条件に応じた redirect 先の変更ができるということになる。 また RedirectFunction は injection context で呼び出されるため inject() を使ったインスタンス取得もできる。

たとえば、次のように任意の class を inject した処理が記述できる。

// app.routes.ts

const redirectToFn: RedirectFunction = () => {
  const isFirstVisit: boolean = inject(AccessCounter).isFirstVisit();
  if (isFirstVisit) return 'home';

  return 'home2';
};

export const routes: Routes = [
  { path: '', redirectTo: redirectToFn, pathMatch: 'full' },
  { path: 'home', component: HomeComponent },
  { path: 'home2', component: Home2Component },
];

注意点としては RedirectFunction が動作する injection context は EnvironmentInjector となるため、inject 対象は providedIn: 'root' で登録されている必要がある。

URL パラメータを使った分岐

injection context で呼び出される関数を指定できることでかなり幅が広がるイメージが湧いたと思う。 しかし、もう一つ注意点がある。それは同期的な関数しか実行できない点である。

例えば、URL のクエリパラメータを見てリダイレクト先を分けたいとする。 inject() を使うことで ActivatedRoute のインスタンスは手に入るが、そこから同期的にクエリパラメータを取り出すことができない。

あらためて公式ドキュメントを見ると RedirectFunction は引数に ActivatedRouteSnapshot の一部のプロパティが渡されることが確認できる。 URL の一部を使って分岐をしたい場合には、引数を利用するとよい。

// app.routes.ts

const redirectToFn: RedirectFunction = (data) => {
  if (data.queryParams['redirect'] === 'home') return 'home';

  return 'home2';
};

export const routes: Routes = [
  { path: '', redirectTo: redirectToFn, pathMatch: 'full' },
  { path: 'home', component: HomeComponent },
  { path: 'home2', component: Home2Component },
];

上記の関数を書くことで ?redirect=home のときは 'home' へ ?redirect=home2 のときは 'home2' に遷移することができる。

まとめ

今回は v18 で入ったアップデートの一つを紹介した。 すぐにみんなが使いたくなるような機能ではないかもしれないが、いざというときとても便利そうだと感じた。

触ってみたときの Stackblitz のコードもおいておく。

https://stackblitz.com/edit/stackblitz-starters-ax1szb

参考リンク