跳至主要内容

API 切片:React Hooks

Hooks 概述

RTK Query 的核心 createApi 方法与 UI 无关,就像 Redux 核心库和 Redux Toolkit 与 UI 无关一样。它们都是可以在任何地方使用的纯 JS 逻辑。

但是,RTK Query 还提供了为每个端点自动生成 React Hooks 的功能。由于这专门依赖于 React 本身,因此 RTK Query 提供了一个替代入口点,该入口点公开了一个包含该功能的 createApi 的自定义版本。

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

如果您使用了 React 特定的 createApi 版本,生成的 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 提供了用于更高级用例的额外钩子,尽管并非所有钩子都直接在Api对象上生成。在createApi的 React 特定版本中生成的钩子完整列表如下

对于上面的示例,api 的完整生成的钩子集如下所示

生成的 React Hook
/* 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)

功能比较

提供的钩子在一定程度上具有功能重叠,以便为特定情况提供优化的选项。下表比较了每个钩子的核心功能。

功能
自动触发查询请求✔️✔️
允许手动触发查询请求✔️✔️✔️✔️✔️
允许手动触发变异请求✔️
订阅组件以将缓存数据保留在存储中✔️✔️✔️✔️✔️
返回存储中的请求状态和缓存数据✔️✔️✔️✔️
随着请求状态和数据变得可用而重新渲染✔️✔️✔️✔️
接受轮询/重新获取选项以触发自动重新获取✔️✔️✔️✔️

useQuery

访问 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作为跳过查询的另一种方式,请参阅skipToken
    • options:一组控制钩子获取行为的选项
  • 返回值
    • 一个查询结果对象,包含当前加载状态、API 调用返回的实际数据或错误、有关请求的元数据以及用于refetch数据的函数。可以使用selectFromResult自定义

描述

一个 React 钩子,它会自动触发从端点获取数据,'订阅'组件到缓存数据,并从 Redux 存储中读取请求状态和缓存数据。组件将在加载状态更改和数据变得可用时重新渲染。

查询参数用作缓存键。更改查询参数将告诉钩子重新获取数据(如果缓存中不存在),并且钩子将在数据可用后返回该查询参数的数据。

此钩子结合了 useQueryStateuseQuerySubscription 的功能,旨在用于大多数情况。

功能

  • 根据钩子参数和缓存数据是否存在自动触发请求以检索数据(默认情况下)
  • “订阅”组件以将缓存数据保留在存储中,并在组件卸载时“取消订阅”
  • 接受轮询/重新获取选项,以便在满足相应条件时触发自动重新获取
  • 返回来自 Redux 存储的最新请求状态和缓存数据
  • 随着请求状态更改和数据变得可用而重新渲染

skipToken

可以传递给 useQueryuseQueryStateuseQuerySubscription,而不是查询参数,以获得与在查询选项中设置 skip: true 相同的效果。

对于以下情况很有用:当 argundefined 时应跳过查询,并且 TypeScript 会对此进行投诉,因为不允许将 arg 作为 undefined 传递,例如

如果查询参数不允许为 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: 一个函数,根据提供的参数触发数据更新。触发函数返回一个带有上面显示的属性的 promise,这些属性可用于处理 promise 的行为
    • mutationState: 一个查询状态对象,包含当前加载状态和有关请求的元数据,或在适用情况下由 selectFromResult 选项返回的值。此外,此对象将包含
      • 一个 reset 方法,用于将钩子重置回其原始状态并从缓存中删除当前结果
      • 一个 originalArgs 属性,包含传递给 trigger 函数的最后一次调用的参数。

描述

一个 React 钩子,允许您为给定端点触发更新请求,并将组件订阅到从 Redux store 读取请求状态。组件将在加载状态更改时重新渲染。

功能

  • 手动控制触发请求以更改服务器上的数据或可能使缓存失效
  • “订阅”组件以将缓存数据保留在存储中,并在组件卸载时“取消订阅”
  • 返回来自 Redux 存储的最新请求状态和缓存数据
  • 随着请求状态更改和数据变得可用而重新渲染

useQueryState

访问 useQuery 钩子
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 自定义

描述

一个 React 钩子,从 Redux store 读取请求状态和缓存数据。组件将在加载状态更改和数据可用时重新渲染。

请注意,此钩子不会触发获取新数据。对于这种情况,请参见 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: 一组控制钩子获取行为的选项
  • 返回值

    • 包含一个用于 refetch 数据的函数的对象

描述

一个 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: 一组控制钩子获取行为的选项。这些选项只有在惰性查询至少被触发一次后才会生效。
  • 返回值: 包含以下内容的元组

    • 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 钩子。

特性

  • 手动控制触发请求以检索数据