Dev Study
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>),
  });
}
公式ドキュメントで詳しく ↗