StencilJSでion-routerを使ってデータのやり取り

**Stencilは万能、これはガチ！**

StencilでPWAを作るときは、

```shell
$ npm init stencil
```

から`ionic-pwa`を選択して始めるのですが、デフォルトでルーティングがIonicの`ion-router`を使用するようになっています。

Ionic単体なら`@angular/router`を使うのですが、Stencilだとどうやってルーティングするの？ってことであまり記事が見当たらなかったのでココ書いときます。

# Ionic3とIonic4のルーティングの違い
# Ionic3の場合
Ionic3の時は、ページのコンポーネントを`NavController`に`push`したり、`pop`してページを遷移していました。
ページ遷移がスタックのような感じでした。

また、ページ間のデータのやり取りも自由で、`NavParams`を使って連想配列だろうがカスタムクラスのインスタンスだろうが何でも遷移先のページに渡すことができました。

## Ionic4の場合
Ionic4では内部で`AngularRouter`が使われています。なので、アプリのrootでページ毎にパスを設定してルーティングするようになりました。
ページ遷移が直線的ですね。

ページ間のやり取りはというと、Ionic3の時の何でも渡せるというのはルーティング使用上あまり推奨はされなくなりました。
id等のユニークな文字列をurlのパラメータとして渡して、遷移先で渡されたデータをサービスに突っ込んで欲しいデータの塊を取得する、という方法が推奨されているようです。

# Stencilでion-routerを使ったルーティング

## パラメータを渡す

```tsx:app-root.tsx
import { Component } from '@stencil/core';
@Component({
  tag: 'app-root',
  styleUrl: 'app-root.css'
})
export class AppRoot {
  render() {
    return (
      <ion-app>
        <ion-router useHash={false}>
          <ion-route url="/" component="app-home" />
          <ion-route url="/register" component="app-register" />
          <ion-route url="/watch/:url" component="app-watch" />
        </ion-router>
        <ion-nav />
      </ion-app>
    );
  }
}
```

`app-root`で`ion-router`を使ってルーティングをしています。このコードは

* app-home
* app-register
* app-watch

の3種類のページへのルーティングを行なっており、app-watchに関してはurlというパラメータを受け取れるという意味です。


では、app-watchに遷移する際にパラメータを渡してみましょう。

```tsx:app-home.tsx
import { Component, Prop, } from '@stencil/core';
@Component({
  tag: 'app-home',
  styleUrl: 'app-home.css'
})
export class AppHome {
  @Prop() videos: any = [];
  constructor() {
    this.videos.push({ name: '動画1', url: '動画1のurl', sourceType: 'youtube', tag: '実況動画' });
    this.videos.push({ name: '動画2', url: '動画2のurl', sourceType: 'youtube', tag: '実況動画' });
    this.videos.push({ name: '動画3', url: '動画3のurl', sourceType: 'youtube', tag: '実況動画' });
    this.videos.push({ name: '動画4', url: '動画4のurl', sourceType: 'youtube', tag: '実況動画' });
    this.videos.push({ name: '動画5', url: '動画5のurl', sourceType: 'youtube', tag: '実況動画' });
  }
  render() {
    return [
      <ion-header>
        <ion-toolbar color="primary">
          <ion-title>Home</ion-title>
        </ion-toolbar>
      </ion-header>,

      <ion-content padding>
        {this.videos.map(video => {
          return <ion-card><ion-item href={'/watch/' + video.url}>
            <ion-card-title>{video.name}</ion-card-title>
          </ion-item></ion-card>
        })}
      </ion-content>
    ];
  }
}
```

ダミーデータで`videos`という変数を作りました。
Ionic3では、クリックしたらクリックイベントに紐づいている関数から`NavController.push()`って感じでページ遷移してましたが、Ionic4 では`href`に`app-root.tsx`で指定したurlを設定するだけでページ遷移ができちゃいます。

ここでは`video.url`をパラメータとしてapp-watchページに渡しています。

## パラメータを受け取る

```tsx:app-watch.tsx
import { Component, Prop } from '@stencil/core';
@Component({
  tag: 'app-watch',
  styleUrl: 'app-watch.css'
})
export class AppWatch {
  @Prop() url:string;
  async componentDidLoad() {
    console.log(this.url);
  }
  render() {
    return [
      <ion-header>
        <ion-toolbar color="primary">
          <ion-title>Watch</ion-title>
        </ion-toolbar>
      </ion-header>,
      <ion-content padding>
        <p>
          Welcome to the PWA Toolkit. You can use this starter to build entire
          apps with web components using Stencil and ionic/core! Check out the
          README for everything that comes in this starter out of the box and
          check out our docs on <a href="https://stenciljs.com">stenciljs.com</a> to get started.
        </p>
      </ion-content>
    ];
  }
}
```

Stencilの`Prop`デコレータを使えば、何と遷移元から渡されたパラメータが代入されます。
なのでコンソールには

```console
動画~のurl
```

と表示されます。

# あとがき
技術書典6のためにStencilの入門本書いてるけど、Stencilできること多いし簡単だしで本書いてて面白い。
興味のある人は4月14日当日ブースに来てもらって話したいところ。
↓はサークルページ
https://techbookfest.org/event/tbf06/circle/60150002