What is Angular Query?
Tags: angular, javascript, typescript, webdev
Published: 2024-02-03 22:43:14

## Short breakdown 👇

Angular Query is used for syncing server data with client applications.

* Without any unneeded abstractions.

**Ideal for**

* grids

* tables

* listings

* etc…

## We have 2 packages to look at

 1. ngneat/query

 2. tanstack/angular-query-experimental

## ngneat is unofficial adapter

* supporting RxJS & Signals by [@ngneat_org](https://twitter.com/ngneat_org) 
[@NetanelBasal](https://twitter.com/NetanelBasal)

## TanStack one is official

* developed by [@Arnoud_dv](https://twitter.com/Arnoud_dv) [@tan_stack](https://twitter.com/tan_stack)

* for now supports only Signals

* RxJS support planned for the future

Both are using **TanStack Query Core.**

## 🟨 Core Concepts 🟨

**1. Queries**

* Declaratively manage data fetching.

* Letting Angular Query handle the timing and specifics of server communication.

**2. Mutations**

* Handle data modification

* Integrating queries for a consistent data management

## 🧹 Cache & Cleanup 🧹

**1. Cache Management**

* Data maintenance and retrieval is handled by Query Client & Query Cache.

**2. Query Keys**

* A system for identifying and managing data dependencies across components.

**3. SWR**

* Ensures data freshness by smartly revalidating data behind the scenes without sacrificing performance.

## 💻 Significant DX improvements 💻

* Reduced boilerplate Out of the box

* Intelligent caching and data management strategies

* Giant performance boost in writing async code

* Pairs fantastic with component state management libraries

**Basic usage with ngneat/query:**

Service usage:
```typescript
    import { injectQuery } from '@ngneat/query';
    
    @Injectable({ providedIn: 'root' })
    export class TodosService {
      #http = inject(HttpClient);
      #query = injectQuery();
    
      getTodos() {
        return this.#query({
          queryKey: ['todos'] as const,
          queryFn: () => {
            return this.http.get<Todo[]>(
              'https://jsonplaceholder.typicode.com/todos',
            );
          },
        });
      }
    }
```
Component usage with **Observables**:
```typescript

    @Component({
      standalone: true,
      template: `
        @if (todos.result$ | async; as result) {
          @if (result.isLoading) {
            <p>Loading</p>
          }
          @if (result.isSuccess) {
            <p>{{ result.data[0].title }}</p>
          }
          @if (result.isError) {
            <p>Error</p>
          }
        }
      `,
    })
    export class TodosPageComponent {
      todos = inject(TodosService).getTodos();
    }
```
Component usage with **Signals**:
```typescript

    @Component({
      standalone: true,
      template: `
        @if (todos().isLoading) {
          Loading
        }
        @if (todos().data; as data) {
          <p>{{ data[0].title }}</p>
        }
        @if (todos().isError) {
          <p>Error</p>
        }
      `,
    })
    export class TodosPageComponent {
      todos = inject(TodosService).getTodos().result;
    }
```
**Docs:**

ngneat: [https://github.com/ngneat/query](https://github.com/ngneat/query)

TanStack: [https://tanstack.com/query/latest/docs/framework/angular/overview](https://tanstack.com/query/latest/docs/framework/angular/overview)

Follow me on X for more: [https://twitter.com/DanielGlejzner](https://twitter.com/DanielGlejzner)