🌟
httpClientのリクエストを、httpResourceに書き換える
httpResource、便利ですね。Signalベースになっていて、リクエスト内部で使っているSignalが書き換わる度に、リクエストを実行します。個人的には、 Resource.reload()
がお気に入りです。おそらくほとんどのAngularユーザが、httpリクエストはService経由に行っており、以下のようなコードを書いていたと思います。
@Injectable({...})
export class ExampleService {
readonly #http = inject(HttpClient);
// Promiseベースで取り回している場合
getDataPromise(id: string): Promise<Data> {
return firstValueFrom(this.#http.get<Data>(environment.api + 'example/' + id));
}
// Observableベース
getDataObservable(id: string): Observable<Data> {
return this.#http.get<Data>(environment.api + 'example/' + id);
}
}
これを、async
pipeを使ってテンプレートに直接反映させていたのか、コンポーネントのプロパティに代入して反映してたのかはそれぞれですが、長らく見慣れたコードでしょう。それが、以下のように書けるようになりました。
@Injectable({...})
export class ExampleService {
readonly #http = inject(HttpClient);
// Promiseベースで取り回している場合
getData(id: Signal<string>): HttpResourceRef<Data> {
return httpResource<Data>(environment.api + 'example/' + id());
}
}
これを、直接コンポーネントのプロパティにバインディングします。
@Component({...})
export class ExamplePage {
readonly id = input.required<number>();
readonly #exampleService = inject(ExampleService);
readonly dataResource = this.#exampleService.getData(this.id);
}
注意することは、Signalから値を取り出すのではなく、Signalごと引数に渡すことぐらいでしょうか。ライフサイクルに左右されず、Signalの値ベースでリクエストがハンドリングできるの、シンプルでめちゃくちゃいいですよね。おすすめです。
Ionic Angularだと、実際のコードは以下のようになります(ViewDidEnterプロパティは https://zenn.dev/rdlabo/articles/bb03d724d33831 をご参考ください)
@Component({...})
export class ExamplePage {
readonly id = input.required<number>();
readonly el = inject(ElementRef);
readonly #didEnter = toSignal(createDidEnter(this.el));
readonly #exampleService = inject(ExampleService);
readonly dataResource = this.#exampleService.getData(this.#didEnter, this.id);
}
@Injectable({...})
export class ExampleService {
readonly #http = inject(HttpClient);
getData(didEnter: Signal<boolean>, id: Signal<string>): HttpResourceRef<Data> {
return httpResource<IMovie[]>(() => {
if (!didEnter()) {
return undefined;
}
return environment.api + 'example/' + id();
});
}
}
以前と比べて随分シンプルに書けるようになりましたね。まだ実験中のAPIですが、ぜひお試しくださいー!
Discussion