⚡ Angular’s rxResource: The Modern Way to Handle Async Data (Angular 19

Async data in Angular has always been a bit of a challenge—especially when juggling loading states, error handling, and subscriptions. But with Angular 19, rxResource changes the game completely.

Let’s break down how we used to handle async data, what the problems were, and how rxResource solves them beautifully.


🧠 The Old-School Way: subscribe() (Avoid This!)

@Component({...})
export class UserListComponent {
private http = inject(HttpClient);
users: { name: string }[] = [];

constructor() {
this.http.get<{ name: string }[]>('https://jsonplaceholder.typicode.com/users')
.subscribe(data => this.users = data);
}
}

🚫 What’s Wrong Here?

  • Manual subscription = potential memory leaks
  • No native handling for loading or errors
  • Clunky, imperative approach

✅ Better: Async Pipe (Cleaner, But Limited)

@Component({...})
export class UserListComponent {
private http = inject(HttpClient);
users$ = this.http.get<{ name: string }[]>('https://jsonplaceholder.typicode.com/users');
}
<ul *ngIf="users$ | async as users; else loading">
<li *ngFor="let user of users">{{ user.name }}</li>
</ul>
<ng-template #loading>Loading...</ng-template>

Pros:

✔️ Auto-unsubscribes
✔️ Cleaner than subscribe()

But Still:

❌ No built-in state tracking
❌ Error handling is manual
❌ Not ideal for reactive workflows with Signals


🚀 Enter rxResource — Angular 19’s Game Changer

Angular 19 introduces rxResource, a smarter, Signal-friendly way to manage async data. It wraps loading, error, and data state into one reactive resource.

@Component({...})
export class UserListComponent {
private http = inject(HttpClient);
users = rxResource(() => this.http.get<{ name: string }[]>('https://jsonplaceholder.typicode.com/users'));
}
<ng-container *ngIf="users.loading(); else content">Loading...</ng-container>
<ng-template #content>
<ng-container *ngIf="users.error(); else userList">
Error: {{ users.error()?.message }}
</ng-container>
</ng-template>
<ng-template #userList>
<ul><li *ngFor="let user of users.data()">{{ user.name }}</li></ul>
</ng-template>

🔥 Why This Rocks:

  • Built-in support for loading, error, and data
  • Fully reactive with Signals
  • Minimal boilerplate
  • No need to unsubscribe — ever

📦 Bonus: rxResource with Parameters + Refresh

@Component({...})
export class UserDetailComponent {
private http = inject(HttpClient);
userId = signal(1);

user = rxResource(() =>
this.http.get<{ name: string }>(`https://jsonplaceholder.typicode.com/users/${this.userId()}`)
);

fetchUser(id: number) {
this.userId.set(id);
this.user.refresh(); // Manually trigger refetch
}
}
<button (click)="fetchUser(1)">User 1</button>
<button (click)="fetchUser(2)">User 2</button>

<div *ngIf="user.loading(); else content">Loading...</div>

<ng-template #content>
<div *ngIf="user.error(); else userInfo">
Error: {{ user.error()?.message }}
</div>
</ng-template>

<ng-template #userInfo>
<p>{{ user.data()?.name }}</p>
</ng-template>

This is next-level reactive programming: easy parameter switching, clean reactivity, and precise control.


🎯 Summary: Why rxResource Is a No-Brainer

Featuresubscribe()async piperxResource
Auto-unsubscribe
Loading state
Error handling
Signal integration
Code readability⚠️

🧠 Final Thoughts

If you’re still manually subscribing or relying solely on async, now’s the time to explore rxResource. It’s reactive, elegant, and built for the modern Angular ecosystem.

Angular 19 is all about signals — and rxResource is how you keep your data reactive, safe, and maintainable

Leave a Comment

Your email address will not be published. Required fields are marked *