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].useQuery
或 api.endpoints[endpointName].useMutation
,與您定義該端點的方式相符。
相同的 hooks 也會新增到 Api
物件本身,並根據端點名稱和查詢/突變類型給予自動產生的名稱。
例如,如果您有端點 getPosts
和 updatePost
,這些選項會可用
// 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
,端點名稱的第一個字母大寫,然後根據類型附加 Query
或 Mutation
。
RTK Query 提供其他 hooks 以供更進階的使用案例,雖然並非所有 hooks 都會直接產生在 Api
物件上。在 React 特定版本的 createApi
中產生的完整 hooks 清單如下
useQuery
(端點特定,也會產生在Api
物件上)useMutation
(端點特定,也會產生在Api
物件上)useQueryState
(端點特定)useQuerySubscription
(端點特定)useLazyQuery
(端點特定,也會產生在Api
物件上)useLazyQuerySubscription
(端點特定)usePrefetch
(與端點無關)
對於上述範例,api 的完整產生 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
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
,作為跳過查詢的替代方式,請參閱 skipTokenoptions
:控制掛鉤擷取行為的一組選項
- 傳回
- 包含目前載入狀態、API 呼叫傳回的實際資料或錯誤、關於請求的元資料,以及
refetch
資料的函式的查詢結果物件。可以使用selectFromResult
自訂
- 包含目前載入狀態、API 呼叫傳回的實際資料或錯誤、關於請求的元資料,以及
說明
React 掛鉤,會自動觸發從端點擷取資料、讓元件「訂閱」快取資料,以及從 Redux 儲存讀取請求狀態和快取資料。元件會在載入狀態變更且資料可用時重新呈現。
查詢參數用作快取金鑰。變更查詢參數會告知掛鉤重新擷取資料(如果資料尚未存在於快取中),而且掛鉤會在資料可用時傳回該查詢參數的資料。
此掛鉤結合了 useQueryState
和 useQuerySubscription
的功能,而且預計會用於大多數情況。
特色
- 根據掛鉤參數和預設快取資料是否存在,自動觸發請求以擷取資料
- 讓元件「訂閱」以保留儲存中的快取資料,並在元件卸載時「取消訂閱」
- 接受輪詢/重新擷取選項,以在符合對應條件時觸發自動重新擷取
- 從 Redux 儲存傳回最新的請求狀態和快取資料
- 在請求狀態變更且資料可用時重新呈現
skipToken
可以傳入 useQuery
、useQueryState
或 useQuerySubscription
,取代查詢參數,以取得與在查詢選項中設定 skip: true
相同的效果。
對於在 arg
為 undefined
且 TypeScript 抱怨的情況,因為 arg
不允許傳入 undefined
,例如
useSomeQuery(arg, { skip: !!arg })
useSomeQuery(arg ?? skipToken)
如果直接傳遞到查詢或變異選擇器中,該選擇器將始終傳回未初始化的狀態。
另請參閱 使用 skipToken
透過 TypeScript 跳過查詢
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
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
作為跳過選取的另一種方式,請參閱 skipTokenoptions
:控制掛鉤回傳值的選項集
傳回
- 包含目前載入狀態、API 呼叫回傳的實際資料或錯誤以及請求相關資訊的查詢結果物件。可用
selectFromResult
自訂
- 包含目前載入狀態、API 呼叫回傳的實際資料或錯誤以及請求相關資訊的查詢結果物件。可用
說明
讀取 Redux 儲存體中的請求狀態和快取資料的 React 掛鉤。載入狀態變更且資料可用時,元件會重新呈現。
請注意,此掛鉤不會觸發擷取新資料。對於此使用案例,請參閱 useQuery
或 useQuerySubscription
。
特色
- 從 Redux 儲存傳回最新的請求狀態和快取資料
- 在請求狀態變更且資料可用時重新呈現
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
作為跳過查詢的另一種方式,請參閱 skipTokenoptions
:控制掛鉤擷取行為的選項集
傳回
- 包含用於
重新擷取
資料的函式的物件
- 包含用於
說明
自動觸發從端點擷取資料,並將元件「訂閱」至快取資料的 React 掛鉤。
查詢引數用作快取金鑰。變更查詢引數會告知掛鉤重新擷取資料,如果資料尚未存在於快取中。
請注意,此掛鉤不會回傳請求狀態或快取資料。對於此使用案例,請參閱 useQuery
或 useQueryState
。
特色
- 根據掛鉤參數和預設快取資料是否存在,自動觸發請求以擷取資料
- 讓元件「訂閱」以保留儲存中的快取資料,並在元件卸載時「取消訂閱」
- 接受輪詢/重新擷取選項,以在符合對應條件時觸發自動重新擷取
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
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
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 勾子,可用於提前啟動資料擷取。
功能
- 手動控制發出請求以擷取資料