This article walks through the process of using the stable @tanstack/query-angular package in Angular v18 applications to handle API requests more effectively 🚀

Handling API calls in Angular projects typically involves writing a lot of repeated code, which can lead to duplication, higher maintenance costs, and tricky state synchronization. Although @tanstack/angular-query-experimental offers a feature-rich option, it remains in an experimental phase and should be used with caution. For Angular v17 and v18 projects, the established @tanstack/query-angular package is a more dependable choice.

Core Advantages of TanStack Angular Query:

Declarative API Definition: Create query functions that encapsulate both the request and any data transformation logic, resulting in cleaner, more maintainable code.

Automatic Caching & Refetching: Take advantage of built-in caching models such as "stale-while-revalidate" to boost performance and minimize redundant network traffic. You can trigger refetches based on various conditions, like data becoming stale or the window regaining focus, to keep information current.

Reactive Data Handling: Manage data using observables and signals, which allows UI components to update reactively without needing manual lifecycle management or complex state solutions.

Modular Structure: Package API logic into reusable query units to improve code organization and ease of maintenance.

Specialized Devtools: Use the TanStack Query Devtools to monitor query activity, cache state, and refetch behavior, making debugging and performance tuning more straightforward.

How to Install:

Use npm or yarn to install the required packages:

npm install @tanstack/query-angular-experimental @tanstack/angular-query-devtools-experimental 
Enter fullscreen mode Exit fullscreen mode

Detailed Implementation Steps:

Even though @tanstack/angular-query-experimental exists, it's still in development and isn't suitable for production environments. For dependable API call management in Angular projects, the stable @tanstack/query-angular package is the recommended path.

Here's a guide to implementing it step by step:

1. Configure Providers in app.config.ts:

import { ApplicationConfig } from '@angular/core';
import { provideRouter } from '@angular/router';

import { routes } from './app.routes';
import { provideHttpClient } from '@angular/common/http';
import { QueryClient, provideAngularQuery } from '@tanstack/angular-query-experimental';

const queryClient = new QueryClient();

export const appConfig: ApplicationConfig = {
  providers: [
    provideRouter(routes),
    provideHttpClient(),
    provideAngularQuery(queryClient)
  ]
};
Enter fullscreen mode Exit fullscreen mode
  • Bring in provideHttpClient, QueryClient, and provideAngularQuery.
  • Create and export the app configuration object by setting up routing, HTTP client, and Angular Query through dependency injection.

2. Create a TypeScript Type for the API Response:

TypeScript types outline the expected shape of your data, which helps for better code structure and preventing bugs. In your app, this type acts as a contract for the data coming back from an API call or another data source.

export type Response = {
  name: string
  description: string
  subscribers_count: number
  stargazers_count: number
  forks_count: number
}
Enter fullscreen mode Exit fullscreen mode

3. Build a Service (repos.service.ts) to Handle the API Call:

import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Response } from '../../types/responce.type';

@Injectable({
  providedIn: 'root'
})
export class ReposService {

  endpoint: string = 'https://api.github.com';

  constructor(
    private http: HttpClient
  ) { }

  getRepos() {
    return this.http.get<Response>(`${this.endpoint}/repos/tanstack/query`);
  }
}
Enter fullscreen mode Exit fullscreen mode

The service's job is to contact the GitHub API for repository information. It leverages HttpClient for the request and expects the response to match the Response type defined earlier.

4. Set Up Angular Query in the Component (github-repo-list.component.ts):

The component relies on Angular Query for data fetching and caching. It takes an instance of ReposService to perform the actual HTTP request. A query is defined with the unique key 'repoData' that utilizes a queryFn to retrieve the repository list.

import { ChangeDetectionStrategy, Component, inject } from '@angular/core';
import { injectQuery } from '@tanstack/angular-query-experimental';
import { AngularQueryDevtools } from '@tanstack/angular-query-devtools-experimental';
import { lastValueFrom } from 'rxjs';
import { ReposService } from '../services/repos/repos.service';

@Component({
  selector: 'app-github-repo-list',
  standalone: true,
  changeDetection: ChangeDetectionStrategy.OnPush,
  imports: [AngularQueryDevtools],
  templateUrl: './github-repo-list.component.html',
  styleUrl: './github-repo-list.component.scss'
})
export class GithubRepoListComponent{

  reposService = inject(ReposService);

  query = injectQuery(() => ({
    queryKey: ['repoData'],
    queryFn: () =>
      lastValueFrom(
        this.reposService.getRepos()
      ),
  }))
}
Enter fullscreen mode Exit fullscreen mode

5. Display the Data in the Component Template (github-repo-list.component.html):

@if (query.isPending()) {
    Loading...
}

@if (query.error()) {
    An error has occurred: {{ query.error()?.message }}
}

@if (query.data(); as data) {
    <h1>Name: {{ data.name }}</h1>
    <p>Description: {{ data.description }}</p>
    <strong>👀 {{ data.subscribers_count }}</strong>
    <strong>✨ {{ data.stargazers_count }}</strong>
    <strong>🍴 {{ data.forks_count }}</strong>
}

<angular-query-devtools initialIsOpen />
Enter fullscreen mode Exit fullscreen mode
  • The markup uses conditionals to show different content based on the query's status—whether it's still loading, encountered an error, or was successful.
  • It gracefully manages each state, offering the user a clear indication of what's happening.
  • It also includes Angular Query devtools to make inspection and debugging easier.

See It in Action:

Angular v18 with TanStack Angular Query

You can find the full source code in this GitHub repository. Thanks 😊