Loading data with resource() and httpResource()
subscribe() calls, hand-rolled state ( loading , error , data ) and memory leaks whenever you forgot an unsubscribe . Since Angular 21, resource() and httpResource() wrap all of that into a reactive primitive built on signals .
The resource() model
resource() ties a reactive request to an async loader . When a signal read in params changes, Angular re-runs the loader automatically and cancels the in-flight request through an AbortSignal . The result is an object of signals: value() , error() , status() , plus isLoading() .
userId is enough: no subscribe , no takeUntilDestroyed . The resource reloads, exposes isLoading() during the call, and aborts the previous request.
httpResource for REST calls
httpResource() is the variant tailored for HttpClient : it runs through interceptors, handles response typing and reacts to URL changes. You give it a function that returns the URL (or a full request object) derived from signals.
async pipe:
States and their gotchas
status() returns one of idle , loading , reloading , resolved , error and local . Two subtleties deserve attention:
- ›
during a reload , value()keeps the previous data (reloading), which avoids a blank
- ›
httpResourceis meant for reads (GET). For a POST/PUT, stick with plainHttpClient:
Why drop manual subscriptions
resource , the dependency becomes declarative — the loader re-runs because a signal changed, full stop. You delete the pagination BehaviorSubject s, the defensive switchMap s and the finalize calls that reset loading to false . The official docs cover the API in the async resource guide .
resource()doesn't replace RxJS: it replaces the plumbing . You describe what to load and what it depends on; Angular handles the when, the cancellation and the state. The component goes back to being a plain read of signals.