跳至主要內容

API 切片:React Hooks

Hooks 總覽

核心 RTK Query createApi 方法與 Redux 核心函式庫和 Redux Toolkit 一樣,與 UI 無關。它們都是可以在任何地方使用的純 JS 邏輯。

不過,RTK Query 還提供自動為每個端點產生 React hooks 的功能。由於這特別依賴 React 本身,因此 RTK Query 提供一個替代的進入點,公開一個自訂版本的 createApi,其中包含該功能

import { createApi } from '@reduxjs/toolkit/query/react'

如果您已使用 createApi 的 React 特定版本,產生的 Api 切片結構也會包含一組 React hooks。主要的端點 hooks 可用於 api.endpoints[endpointName].useQueryapi.endpoints[endpointName].useMutation,與您定義該端點的方式相符。

相同的 hooks 也會新增到 Api 物件本身,並根據端點名稱和查詢/突變類型給予自動產生的名稱。

例如,如果您有端點 getPostsupdatePost,這些選項會可用

產生的 React Hook 名稱
// Hooks attached to the endpoint definition
const { data } = api.endpoints.getPosts.useQuery()
const [updatePost, { data }] = api.endpoints.updatePost.useMutation()

// Same hooks, but given unique names and attached to the API slice object
const { data } = api.useGetPostsQuery()
const [updatePost, { data }] = api.useUpdatePostMutation()

一般格式為 use(Endpointname)(Query|Mutation) - 前綴為 use,端點名稱的第一個字母大寫,然後根據類型附加 QueryMutation

RTK Query 提供其他 hooks 以供更進階的使用案例,雖然並非所有 hooks 都會直接產生在 Api 物件上。在 React 特定版本的 createApi 中產生的完整 hooks 清單如下

對於上述範例,api 的完整產生 hooks 會如下所示

產生的 React Hooks
/* Hooks attached to the `getPosts` query endpoint definition */
api.endpoints.getPosts.useQuery(arg, options)
api.endpoints.getPosts.useQueryState(arg, options)
api.endpoints.getPosts.useQuerySubscription(arg, options)
api.endpoints.getPosts.useLazyQuery(options)
api.endpoints.getPosts.useLazyQuerySubscription(options)

/* Hooks attached to the `updatePost` mutation endpoint definition */
api.endpoints.updatePost.useMutation(options)

/* Hooks attached to the `Api` object */
api.useGetPostsQuery(arg, options) // same as api.endpoints.getPosts.useQuery
api.useLazyGetPostsQuery(options) // same as api.endpoints.getPosts.useLazyQuery
api.useUpdatePostMutation(options) // same as api.endpoints.updatePost.useMutation
api.usePrefetch(endpointName, options)

功能比較

提供的 hooks 有某種程度的功能重疊,以提供針對特定情況最佳化的選項。下表比較每個 hook 的核心功能。

功能
自動觸發查詢要求✔️✔️
允許手動觸發查詢要求✔️✔️✔️✔️✔️
允許手動觸發突變要求✔️
訂閱元件以將快取資料保留在儲存體中✔️✔️✔️✔️✔️
傳回要求狀態和來自儲存體的快取資料✔️✔️✔️✔️
在要求狀態和資料可用時重新呈現✔️✔️✔️✔️
接受輪詢/重新擷取選項以觸發自動重新擷取✔️✔️✔️✔️

useQuery

存取 useQuery hook
const useQueryResult = api.endpoints.getPosts.useQuery(arg, options)
// or
const useQueryResult = api.useGetPostsQuery(arg, options)

簽章

type UseQuery = (
arg: any | SkipToken,
options?: UseQueryOptions,
) => UseQueryResult

type UseQueryOptions = {
pollingInterval?: number
skipPollingIfUnfocused?: boolean
refetchOnReconnect?: boolean
refetchOnFocus?: boolean
skip?: boolean
refetchOnMountOrArgChange?: boolean | number
selectFromResult?: (result: UseQueryStateDefaultResult) => any
}

type UseQueryResult<T> = {
// Base query state
originalArgs?: unknown // Arguments passed to the query
data?: T // The latest returned result regardless of hook arg, if present
currentData?: T // The latest returned result for the current hook arg, if present
error?: unknown // Error result if present
requestId?: string // A string generated by RTK Query
endpointName?: string // The name of the given endpoint for the query
startedTimeStamp?: number // Timestamp for when the query was initiated
fulfilledTimeStamp?: number // Timestamp for when the query was completed

// Derived request status booleans
isUninitialized: boolean // Query has not started yet.
isLoading: boolean // Query is currently loading for the first time. No data yet.
isFetching: boolean // Query is currently fetching, but might have data from an earlier request.
isSuccess: boolean // Query has data from a successful load.
isError: boolean // Query is currently in an "error" state.

refetch: () => QueryActionCreatorResult // A function to force refetch the query - returns a Promise with additional methods
}
  • 參數
    • arg:用於建構查詢本身的查詢參數,以及作為查詢的快取金鑰。您也可以在此傳入 skipToken,作為跳過查詢的替代方式,請參閱 skipToken
    • options:控制掛鉤擷取行為的一組選項
  • 傳回
    • 包含目前載入狀態、API 呼叫傳回的實際資料或錯誤、關於請求的元資料,以及 refetch 資料的函式的查詢結果物件。可以使用 selectFromResult 自訂

說明

React 掛鉤,會自動觸發從端點擷取資料、讓元件「訂閱」快取資料,以及從 Redux 儲存讀取請求狀態和快取資料。元件會在載入狀態變更且資料可用時重新呈現。

查詢參數用作快取金鑰。變更查詢參數會告知掛鉤重新擷取資料(如果資料尚未存在於快取中),而且掛鉤會在資料可用時傳回該查詢參數的資料。

此掛鉤結合了 useQueryStateuseQuerySubscription 的功能,而且預計會用於大多數情況。

特色

  • 根據掛鉤參數和預設快取資料是否存在,自動觸發請求以擷取資料
  • 讓元件「訂閱」以保留儲存中的快取資料,並在元件卸載時「取消訂閱」
  • 接受輪詢/重新擷取選項,以在符合對應條件時觸發自動重新擷取
  • 從 Redux 儲存傳回最新的請求狀態和快取資料
  • 在請求狀態變更且資料可用時重新呈現

skipToken

可以傳入 useQueryuseQueryStateuseQuerySubscription,取代查詢參數,以取得與在查詢選項中設定 skip: true 相同的效果。

對於在 argundefined 且 TypeScript 抱怨的情況,因為 arg 不允許傳入 undefined,例如

如果查詢參數不允許為未定義,將會發生錯誤
useSomeQuery(arg, { skip: !!arg })
改用 skipToken
useSomeQuery(arg ?? skipToken)

如果直接傳遞到查詢或變異選擇器中,該選擇器將始終傳回未初始化的狀態。

另請參閱 使用 skipToken 透過 TypeScript 跳過查詢

useMutation

存取 useMutation 勾子
const useMutationResult = api.endpoints.updatePost.useMutation(options)
// or
const useMutationResult = api.useUpdatePostMutation(options)

簽章

type UseMutation = (
options?: UseMutationStateOptions,
) => [UseMutationTrigger, UseMutationResult | SelectedUseMutationResult]

type UseMutationStateOptions = {
// A method to determine the contents of `UseMutationResult`
selectFromResult?: (result: UseMutationStateDefaultResult) => any
// A string used to enable shared results across hook instances which have the same key
fixedCacheKey?: string
}

type UseMutationTrigger<T> = (arg: any) => Promise<
{ data: T } | { error: BaseQueryError | SerializedError }
> & {
requestId: string // A string generated by RTK Query
abort: () => void // A method to cancel the mutation promise
unwrap: () => Promise<T> // A method to unwrap the mutation call and provide the raw response/error
reset: () => void // A method to manually unsubscribe from the mutation call and reset the result to the uninitialized state
}

type UseMutationResult<T> = {
// Base query state
originalArgs?: unknown // Arguments passed to the latest mutation call. Not available if using the `fixedCacheKey` option
data?: T // Returned result if present
error?: unknown // Error result if present
endpointName?: string // The name of the given endpoint for the mutation
fulfilledTimestamp?: number // Timestamp for when the mutation was completed

// Derived request status booleans
isUninitialized: boolean // Mutation has not been fired yet
isLoading: boolean // Mutation has been fired and is awaiting a response
isSuccess: boolean // Mutation has data from a successful call
isError: boolean // Mutation is currently in an "error" state
startedTimeStamp?: number // Timestamp for when the latest mutation was initiated

reset: () => void // A method to manually unsubscribe from the mutation call and reset the result to the uninitialized state
}
提示

產生的 UseMutation 勾子會在觸發回呼執行後預設重新渲染元件,因為它會影響結果的屬性。如果您想呼叫觸發,但不在乎使用勾子訂閱結果,您可以使用 selectFromResult 選項來限制勾子關心的屬性。

傳回一個完全空的物件表示任何個別的變異呼叫最多只會造成一次重新渲染,例如

selectFromResult: () => ({})
  • 參數

    • options:控制勾子訂閱行為的一組選項
      • selectFromResult:一個可自訂變異結果的回呼,作為組元第二個項目傳回
      • fixedCacheKey:一個選擇性的字串,用於啟用勾子執行個體間的共用結果
  • 傳回:包含下列內容的組元

    • trigger:一個根據提供的引數觸發資料更新的函式。觸發函式傳回一個承諾,其中包含上述可能用於處理承諾行為的屬性
    • mutationState:一個查詢狀態物件,包含目前載入狀態和關於請求的元資料,或適用的 selectFromResult 選項傳回的值。此外,此物件將包含
      • 一個 reset 方法,用於將勾子重設回其原始狀態,並從快取中移除目前的結果
      • 一個 originalArgs 屬性,其中包含傳遞給 trigger 函式最後一次呼叫的引數。

說明

一個 React 勾子,讓您觸發給定端點的更新請求,並訂閱元件以從 Redux 儲存區讀取請求狀態。元件會在載入狀態變更時重新渲染。

特色

  • 手動控制發出請求以變更伺服器上的資料或可能使快取無效
  • 讓元件「訂閱」以保留儲存中的快取資料,並在元件卸載時「取消訂閱」
  • 從 Redux 儲存傳回最新的請求狀態和快取資料
  • 在請求狀態變更且資料可用時重新呈現

useQueryState

存取 useQuery hook
const useQueryStateResult = api.endpoints.getPosts.useQueryState(arg, options)

簽章

type UseQueryState = (
arg: any | SkipToken,
options?: UseQueryStateOptions,
) => UseQueryStateResult | SelectedQueryStateResult

type UseQueryStateOptions = {
skip?: boolean
selectFromResult?: (result: UseQueryStateDefaultResult) => any
}

type UseQueryStateResult<T> = {
// Base query state
originalArgs?: unknown // Arguments passed to the query
data?: T // The latest returned result regardless of hook arg, if present
currentData?: T // The latest returned result for the current hook arg, if present
error?: unknown // Error result if present
requestId?: string // A string generated by RTK Query
endpointName?: string // The name of the given endpoint for the query
startedTimeStamp?: number // Timestamp for when the query was initiated
fulfilledTimeStamp?: number // Timestamp for when the query was completed

isUninitialized: false // Query has not started yet.
isLoading: false // Query is currently loading for the first time. No data yet.
isFetching: false // Query is currently fetching, but might have data from an earlier request.
isSuccess: false // Query has data from a successful load.
isError: false // Query is currently in an "error" state.
}
  • 參數

    • arg:傳遞至端點中定義的查詢的引數。您也可以在此傳遞 skipToken 作為跳過選取的另一種方式,請參閱 skipToken
    • options:控制掛鉤回傳值的選項集
  • 傳回

    • 包含目前載入狀態、API 呼叫回傳的實際資料或錯誤以及請求相關資訊的查詢結果物件。可用 selectFromResult 自訂

說明

讀取 Redux 儲存體中的請求狀態和快取資料的 React 掛鉤。載入狀態變更且資料可用時,元件會重新呈現。

請注意,此掛鉤不會觸發擷取新資料。對於此使用案例,請參閱 useQueryuseQuerySubscription

特色

  • 從 Redux 儲存傳回最新的請求狀態和快取資料
  • 在請求狀態變更且資料可用時重新呈現

useQuerySubscription

存取 useQuerySubscription 掛鉤
const { refetch } = api.endpoints.getPosts.useQuerySubscription(arg, options)

簽章

type UseQuerySubscription = (
arg: any | SkipToken,
options?: UseQuerySubscriptionOptions,
) => UseQuerySubscriptionResult

type UseQuerySubscriptionOptions = {
skip?: boolean
refetchOnMountOrArgChange?: boolean | number
pollingInterval?: number
skipPollingIfUnfocused?: boolean
refetchOnReconnect?: boolean
refetchOnFocus?: boolean
}

type UseQuerySubscriptionResult = {
refetch: () => void // A function to force refetch the query
}
  • 參數

    • arg:傳遞至端點中定義的查詢的引數。您也可以在此傳遞 skipToken 作為跳過查詢的另一種方式,請參閱 skipToken
    • options:控制掛鉤擷取行為的選項集
  • 傳回

    • 包含用於重新擷取資料的函式的物件

說明

自動觸發從端點擷取資料,並將元件「訂閱」至快取資料的 React 掛鉤。

查詢引數用作快取金鑰。變更查詢引數會告知掛鉤重新擷取資料,如果資料尚未存在於快取中。

請注意,此掛鉤不會回傳請求狀態或快取資料。對於此使用案例,請參閱 useQueryuseQueryState

特色

  • 根據掛鉤參數和預設快取資料是否存在,自動觸發請求以擷取資料
  • 讓元件「訂閱」以保留儲存中的快取資料,並在元件卸載時「取消訂閱」
  • 接受輪詢/重新擷取選項,以在符合對應條件時觸發自動重新擷取

useLazyQuery

存取 useLazyQuery 掛鉤
const [trigger, result, lastPromiseInfo] =
api.endpoints.getPosts.useLazyQuery(options)
// or
const [trigger, result, lastPromiseInfo] = api.useLazyGetPostsQuery(options)

簽章

type UseLazyQuery = (
options?: UseLazyQueryOptions
) => [UseLazyQueryTrigger, UseQueryStateResult, UseLazyQueryLastPromiseInfo]

type UseLazyQueryOptions = {
pollingInterval?: number
skipPollingIfUnfocused?: boolean
refetchOnReconnect?: boolean
refetchOnFocus?: boolean
selectFromResult?: (result: UseQueryStateDefaultResult) => any
}

type UseLazyQueryTrigger<T> = (arg: any, preferCacheValue?: boolean) => Promise<
QueryResultSelectorResult
> & {
arg: unknown // Whatever argument was provided to the query
requestId: string // A string generated by RTK Query
subscriptionOptions: SubscriptionOptions // The values used for the query subscription
abort: () => void // A method to cancel the query promise
unwrap: () => Promise<T> // A method to unwrap the query call and provide the raw response/error
unsubscribe: () => void // A method used to manually unsubscribe from the query results
refetch: () => void // A method used to re-run the query. In most cases when using a lazy query, you will never use this and should prefer to call the trigger again.
updateSubscriptionOptions: (options: SubscriptionOptions) () => void // A method used to update the subscription options (eg. pollingInterval)
}

type UseQueryStateResult<T> = {
// Base query state
originalArgs?: unknown // Arguments passed to the query
data?: T // The latest returned result regardless of trigger arg, if present
currentData?: T // The latest returned result for the trigger arg, if present
error?: unknown // Error result if present
requestId?: string // A string generated by RTK Query
endpointName?: string // The name of the given endpoint for the query
startedTimeStamp?: number // Timestamp for when the query was initiated
fulfilledTimeStamp?: number // Timestamp for when the query was completed

isUninitialized: false // Query has not started yet.
isLoading: false // Query is currently loading for the first time. No data yet.
isFetching: false // Query is currently fetching, but might have data from an earlier request.
isSuccess: false // Query has data from a successful load.
isError: false // Query is currently in an "error" state.
}

type UseLazyQueryLastPromiseInfo = {
lastArg: any
}
  • 參數

    • options:控制掛鉤擷取行為和回傳結果值的選項集。影響擷取行為的選項僅在至少觸發一次延遲查詢後才會生效。
  • 傳回:包含下列內容的組元

    • trigger:呼叫時會擷取端點對應資料的函式
    • result:包含目前載入狀態、API 呼叫回傳的實際資料或錯誤以及請求相關資訊的查詢結果物件。可用 selectFromResult 自訂
    • lastPromiseInfo:包含用於呼叫觸發函式的最後一個引數的物件

說明

類似於 useQuery 的 React 掛鉤,但可以手動控制資料擷取發生的時間。

此掛鉤包含 useLazyQuerySubscription 的功能。

特色

  • 手動控制發出請求以擷取資料
  • 讓元件「訂閱」以保留儲存中的快取資料,並在元件卸載時「取消訂閱」
  • 從 Redux 儲存傳回最新的請求狀態和快取資料
  • 在請求狀態變更且資料可用時重新呈現
  • 接受輪詢/重新擷取選項,在符合對應條件且手動呼叫擷取至少一次時,觸發自動重新擷取

注意

當從 LazyQuery 傳回的觸發函式被呼叫時,它總是會向伺服器發起新的請求,即使有快取資料。如果要讓它在存在快取值時立即傳回快取值,請將 preferCacheValue(函式的第二個引數)設定為 true

useLazyQuerySubscription

存取 useLazyQuerySubscription 勾子
const [trigger, lastArg] =
api.endpoints.getPosts.useLazyQuerySubscription(options)

簽章

type UseLazyQuerySubscription = (
options?: UseLazyQuerySubscriptionOptions,
) => [UseLazyQuerySubscriptionTrigger, LastArg]

type UseLazyQuerySubscriptionOptions = {
pollingInterval?: number
skipPollingIfUnfocused?: boolean
refetchOnReconnect?: boolean
refetchOnFocus?: boolean
}

type UseLazyQuerySubscriptionTrigger = (
arg: any,
preferCacheValue?: boolean,
) => void
  • 參數

    • options:控制勾子擷取行為的一組選項。這些選項僅在觸發 Lazy Query 至少一次後才會生效。
  • 傳回:包含下列內容的組元

    • trigger:呼叫時會擷取端點對應資料的函式
    • lastArg:用於呼叫觸發函式的最後一個引數

說明

useQuerySubscription 類似的 React 勾子,但可以手動控制資料擷取發生的時間。

請注意,此勾子不會傳回請求狀態或快取資料。對於該使用案例,請參閱 useLazyQuery

特色

  • 手動控制發出請求以擷取資料
  • 讓元件「訂閱」以保留儲存中的快取資料,並在元件卸載時「取消訂閱」
  • 接受輪詢/重新擷取選項,在符合對應條件且手動呼叫擷取至少一次時,觸發自動重新擷取

usePrefetch

存取 usePrefetch 勾子
const prefetchCallback = api.usePrefetch(endpointName, options)

簽章

type UsePrefetch = (
endpointName: string,
options?: UsePrefetchOptions,
) => PrefetchCallback

type UsePrefetchOptions =
| {
// If specified, only runs the query if the difference between `new Date()` and the last
// `fulfilledTimeStamp` is greater than the given value (in seconds)
ifOlderThan?: false | number
}
| {
// If `force: true`, it will ignore the `ifOlderThan` value if it is set and the query
// will be run even if it exists in the cache.
force?: boolean
}

type PrefetchCallback = (arg: any, options?: UsePrefetchOptions) => void
  • 參數

    • endpointName:要預先擷取資料的端點名稱
    • options:控制是否應執行預先擷取請求的一組選項
  • 傳回

    • 當呼叫時,會啟動擷取所提供端點資料的 prefetch 回呼

說明

一個 React 勾子,可用於提前啟動資料擷取。

功能

  • 手動控制發出請求以擷取資料