Framework
Version

Queries deaktivieren/pausieren

Wenn Sie eine Abfrage jemals daran hindern möchten, automatisch ausgeführt zu werden, können Sie die Option enabled = false verwenden. Die Option enabled akzeptiert auch eine Callback-Funktion, die einen Booleschen Wert zurückgibt.

Wenn enabled false ist

  • Wenn die Abfrage gecachte Daten hat, wird die Abfrage im Zustand status === 'success' oder isSuccess initialisiert.
  • Wenn die Abfrage keine gecachten Daten hat, startet die Abfrage im Zustand status === 'pending' und fetchStatus === 'idle'.
  • Die Abfrage wird beim Mounten nicht automatisch abgerufen.
  • Die Abfrage wird nicht automatisch im Hintergrund erneut abgerufen.
  • Die Abfrage ignoriert Aufrufe von invalidateQueries und refetchQueries des Query Clients, die normalerweise dazu führen würden, dass die Abfrage erneut abgerufen wird.
  • refetch, das von injectQuery zurückgegeben wird, kann verwendet werden, um die Abfrage manuell zum Abrufen auszulösen. Es funktioniert jedoch nicht mit skipToken.

TypeScript-Benutzer bevorzugen möglicherweise skipToken als Alternative zu enabled = false.

angular-ts
@Component({
  selector: 'todos',
  template: `<div>
    <button (click)="query.refetch()">Fetch Todos</button>

    @if (query.data()) {
      <ul>
        @for (todo of query.data(); track todo.id) {
          <li>{{ todo.title }}</li>
        }
      </ul>
    } @else {
      @if (query.isError()) {
        <span>Error: {{ query.error().message }}</span>
      } @else if (query.isLoading()) {
        <span>Loading...</span>
      } @else if (!query.isLoading() && !query.isError()) {
        <span>Not ready ...</span>
      }
    }

    <div>{{ query.isLoading() ? 'Fetching...' : '' }}</div>
  </div>`,
})
export class TodosComponent {
  query = injectQuery(() => ({
    queryKey: ['todos'],
    queryFn: fetchTodoList,
    enabled: false,
  }))
}
@Component({
  selector: 'todos',
  template: `<div>
    <button (click)="query.refetch()">Fetch Todos</button>

    @if (query.data()) {
      <ul>
        @for (todo of query.data(); track todo.id) {
          <li>{{ todo.title }}</li>
        }
      </ul>
    } @else {
      @if (query.isError()) {
        <span>Error: {{ query.error().message }}</span>
      } @else if (query.isLoading()) {
        <span>Loading...</span>
      } @else if (!query.isLoading() && !query.isError()) {
        <span>Not ready ...</span>
      }
    }

    <div>{{ query.isLoading() ? 'Fetching...' : '' }}</div>
  </div>`,
})
export class TodosComponent {
  query = injectQuery(() => ({
    queryKey: ['todos'],
    queryFn: fetchTodoList,
    enabled: false,
  }))
}

Das dauerhafte Deaktivieren einer Abfrage verzichtet auf viele großartige Funktionen, die TanStack Query zu bieten hat (wie z. B. Hintergrund-Refetches), und ist auch nicht der idiomatische Weg. Es bringt Sie vom deklarativen Ansatz (Definition von Abhängigkeiten, wann Ihre Abfrage ausgeführt werden soll) in einen imperativen Modus (rufen Sie ab, wenn ich hier klicke). Es ist auch nicht möglich, Parameter an refetch zu übergeben. Oftmals möchten Sie nur eine Lazy Query, die den anfänglichen Abruf verzögert

Lazy Queries

Die enabled-Option kann nicht nur zum dauerhaften Deaktivieren einer Abfrage verwendet werden, sondern auch, um sie zu einem späteren Zeitpunkt zu aktivieren/deaktivieren. Ein gutes Beispiel wäre ein Filterformular, bei dem Sie die erste Anfrage erst auslösen möchten, sobald der Benutzer einen Filterwert eingegeben hat

angular-ts
@Component({
  selector: 'todos',
  template: `
    <div>
      // 🚀 applying the filter will enable and execute the query
      <filters-form onApply="filter.set" />
      <todos-table data="query.data()" />
    </div>
  `,
})
export class TodosComponent {
  filter = signal('')

  todosQuery = injectQuery(() => ({
    queryKey: ['todos', this.filter()],
    queryFn: () => fetchTodos(this.filter()),
    enabled: !!this.filter(),
  }))
}
@Component({
  selector: 'todos',
  template: `
    <div>
      // 🚀 applying the filter will enable and execute the query
      <filters-form onApply="filter.set" />
      <todos-table data="query.data()" />
    </div>
  `,
})
export class TodosComponent {
  filter = signal('')

  todosQuery = injectQuery(() => ({
    queryKey: ['todos', this.filter()],
    queryFn: () => fetchTodos(this.filter()),
    enabled: !!this.filter(),
  }))
}

isLoading (Früher: isInitialLoading)

Lazy Queries sind von Anfang an im Zustand status: 'pending', da pending bedeutet, dass noch keine Daten vorhanden sind. Dies ist technisch gesehen korrekt, aber da wir derzeit keine Daten abrufen (da die Abfrage nicht *enabled* ist), bedeutet dies auch, dass Sie dieses Flag wahrscheinlich nicht zum Anzeigen eines Lade-Spinners verwenden können.

Wenn Sie deaktivierte oder Lazy Queries verwenden, können Sie stattdessen das Flag isLoading verwenden. Es ist ein abgeleitetes Flag, das berechnet wird aus

isPending && isFetching

sodass es nur dann true ist, wenn die Abfrage gerade zum ersten Mal abgerufen wird.

Typsicheres Deaktivieren von Abfragen mit skipToken

Wenn Sie TypeScript verwenden, können Sie skipToken verwenden, um eine Abfrage zu deaktivieren. Dies ist nützlich, wenn Sie eine Abfrage basierend auf einer Bedingung deaktivieren möchten, aber die Abfrage trotzdem typsicher halten möchten.

WICHTIG: refetch von injectQuery funktioniert nicht mit skipToken. Ansonsten funktioniert skipToken genauso wie enabled: false.

angular-ts
import { skipToken, injectQuery } from '@tanstack/query-angular'

@Component({
  selector: 'todos',
  template: `
    <div>
      // 🚀 applying the filter will enable and execute the query
      <filters-form onApply="filter.set" />
      <todos-table data="query.data()" />
    </div>
  `,
})
export class TodosComponent {
  filter = signal('')

  todosQuery = injectQuery(() => ({
    queryKey: ['todos', this.filter()],
    queryFn: this.filter() ? () => fetchTodos(this.filter()) : skipToken,
  }))
}
import { skipToken, injectQuery } from '@tanstack/query-angular'

@Component({
  selector: 'todos',
  template: `
    <div>
      // 🚀 applying the filter will enable and execute the query
      <filters-form onApply="filter.set" />
      <todos-table data="query.data()" />
    </div>
  `,
})
export class TodosComponent {
  filter = signal('')

  todosQuery = injectQuery(() => ({
    queryKey: ['todos', this.filter()],
    queryFn: this.filter() ? () => fetchTodos(this.filter()) : skipToken,
  }))
}