查詢是基於唯一鍵與非同步資料來源綁定的宣告式依賴關係。查詢可與任何基於 Promise 的方法(包括 GET 和 POST 方法)一起使用,從伺服器獲取資料。若您的方法會修改伺服器上的資料,建議改用變更 (Mutations)。
要在元件或服務中訂閱查詢,請調用 injectQuery 並至少提供以下參數:
import { injectQuery } from '@tanstack/angular-query-experimental'
export class TodosComponent {
info = injectQuery(() => ({ queryKey: ['todos'], queryFn: fetchTodoList }))
}
import { injectQuery } from '@tanstack/angular-query-experimental'
export class TodosComponent {
info = injectQuery(() => ({ queryKey: ['todos'], queryFn: fetchTodoList }))
}
您提供的唯一鍵會在內部用於重新獲取、快取及在應用程式中共享查詢。
injectQuery 回傳的查詢結果包含所有與查詢相關的資訊,可供模板渲染或其他資料使用:
result = injectQuery(() => ({ queryKey: ['todos'], queryFn: fetchTodoList }))
result = injectQuery(() => ({ queryKey: ['todos'], queryFn: fetchTodoList }))
result 物件包含幾個非常重要的狀態,您需要了解這些狀態才能有效使用。查詢在任何時刻只能處於以下其中一種狀態:
除了這些主要狀態外,根據查詢的狀態還可獲取更多資訊:
對於大多數查詢,通常只需先檢查 isPending 狀態,再檢查 isError 狀態,最後即可假設資料已可用並渲染成功狀態:
@Component({
selector: 'todos',
standalone: true,
template: `
@if (todos.isPending()) {
<span>Loading...</span>
} @else if (todos.isError()) {
<span>Error: {{ todos.error()?.message }}</span>
} @else {
<!-- 此時可假設 status === 'success' -->
@for (todo of todos.data(); track todo.id) {
<li>{{ todo.title }}</li>
} @empty {
<li>No todos found</li>
}
}
`,
})
export class PostsComponent {
todos = injectQuery(() => ({
queryKey: ['todos'],
queryFn: fetchTodoList,
}))
}
@Component({
selector: 'todos',
standalone: true,
template: `
@if (todos.isPending()) {
<span>Loading...</span>
} @else if (todos.isError()) {
<span>Error: {{ todos.error()?.message }}</span>
} @else {
<!-- 此時可假設 status === 'success' -->
@for (todo of todos.data(); track todo.id) {
<li>{{ todo.title }}</li>
} @empty {
<li>No todos found</li>
}
}
`,
})
export class PostsComponent {
todos = injectQuery(() => ({
queryKey: ['todos'],
queryFn: fetchTodoList,
}))
}
若不喜歡使用布林值,也可以直接使用 status 狀態:
@Component({
selector: 'todos',
standalone: true,
template: `
@switch (todos.status()) {
@case ('pending') {
<span>Loading...</span>
}
@case ('error') {
<span>Error: {{ todos.error()?.message }}</span>
}
<!-- 雖然 status === 'success',但使用 "else" 邏輯也適用 -->
@default {
<ul>
@for (todo of todos.data(); track todo.id) {
<li>{{ todo.title }}</li>
} @empty {
<li>No todos found</li>
}
</ul>
}
}
`,
})
class TodosComponent {}
@Component({
selector: 'todos',
standalone: true,
template: `
@switch (todos.status()) {
@case ('pending') {
<span>Loading...</span>
}
@case ('error') {
<span>Error: {{ todos.error()?.message }}</span>
}
<!-- 雖然 status === 'success',但使用 "else" 邏輯也適用 -->
@default {
<ul>
@for (todo of todos.data(); track todo.id) {
<li>{{ todo.title }}</li>
} @empty {
<li>No todos found</li>
}
</ul>
}
}
`,
})
class TodosComponent {}
若您在存取 data 前已檢查過 pending 和 error,TypeScript 也會正確縮小 data 的型別範圍。
除了 status 欄位外,您還會獲得一個額外的 fetchStatus 屬性,其選項如下:
背景重新獲取與過期資料重新驗證邏輯會導致 status 和 fetchStatus 的所有組合都可能出現。例如:
因此請記住,查詢可能處於 pending 狀態但實際上並未獲取資料。簡單來說: