← Angular コース
33. resource() — 非同期データをシグナルで扱う
v22で正式版になった resource() は、APIからの非同期取得をシグナルの世界に取り込む仕組みです。resource({ params, loader }) と書くと、params が返すシグナルの値が変わるたびに loader が自動で再実行され、結果がシグナルとして手に入ります。以前のように ngOnInit で subscribe して状態へ詰め替える定型コードが不要になります。
取得した値は value()、読み込み中かどうかは isLoading()、エラーは error()、状態の文字列は status()('idle' / 'loading' / 'resolved' / 'error' など)で読み取れます。すべてシグナルなので、テンプレートで @if (userResource.isLoading()) { ... } と書けば、読み込み中・成功・失敗の表示分けがそのまま素直に書けます。
強みは、依存するシグナル(下の例では userId)が変わると自動で再取得が走り、古いリクエストは中断(abort)してくれることです。「IDが変わるたびに最新の1件を取り直す」といった処理が、購読の管理を自分で書かずに実現できます。前のレッスンの subscribe 方式は今も使えますが、シグナル中心の新規コードでは resource() が第一候補です。
サンプルコード(フレームワーク環境が必要なため表示のみ)
import { Component, signal, resource } from '@angular/core';
type User = { id: number; name: string };
@Component({
selector: 'app-user-card',
// 状態に応じて表示を出し分ける。すべてシグナルとして読める
template:
'@if (userResource.isLoading()) {' +
' <p>読み込み中...</p>' +
'} @else if (userResource.error()) {' +
' <p>取得に失敗しました</p>' +
'} @else {' +
' <p>{{ userResource.value()?.name }}</p>' +
'}',
})
export class UserCardComponent {
userId = signal(1);
// userId が変わるたびに loader が自動で再実行される
userResource = resource({
params: () => ({ id: this.userId() }),
loader: ({ params }) =>
fetch(`/api/users/${params.id}`).then((r) => r.json() as Promise<User>),
});
}