跳到主要内容

 

API 切片:React 钩子

钩子概述

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

然而,RTK Query 也提供了为每个端点自动生成 React 钩子的能力。由于这特别依赖于 React 本身,RTK Query 提供了一个替代的入口点,该入口点公开了一个包含该功能的 createApi 的定制版本:

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

如果你使用了 React 特定版本的 createApi,生成的 Api 切片结构也将包含一组 React 钩子。主要的端点钩子可以通过 api.endpoints[endpointName].useQueryapi.endpoints[endpointName].useMutation 获取,这与你定义该端点的方式相匹配。

同样的钩子也被添加到 Api 对象本身,并根据端点名称和查询/变异类型自动生成名称。

例如,如果你有 getPostsupdatePost 的端点,这些选项将可用:

生成的 React 钩子名称
// 钩子附加到端点定义
const { data } = api.endpoints.getPosts.useQuery()
const [updatePost, { data }] = api.endpoints.updatePost.useMutation()

// 相同的钩子,但给出了唯一的名称并附加到 API 切片对象
const { data } = api.useGetPostsQuery()
const [updatePost, { data }] = api.useUpdatePostMutation()

一般格式是 use(Endpointname)(Query|Mutation) - use 是前缀,你的端点名称的第一个字母大写,然后根据类型追加 QueryMutation

RTK Query 提供了额外的钩子用于更高级的用例,尽管并非所有的钩子都直接在 Api 对象上生成。在 createApi 的 React 特定版本中生成的钩子的完整列表如下:

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

生成的 React 钩子
/* 附加到 `getPosts` 查询端点定义的钩子 */
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)

/* 附加到 `updatePost` 变异端点定义的钩子 */
api.endpoints.updatePost.useMutation(options)

/* 附加到 `Api` 对象的钩子 */
api.useGetPostsQuery(arg, options) // 与 api.endpoints.getPosts.useQuery 相同
api.useLazyGetPostsQuery(options) // 与 api.endpoints.getPosts.useLazyQuery 相同
api.useUpdatePostMutation(options) // 与 api.endpoints.updatePost.useMutation 相同
api.usePrefetch(endpointName, options)

功能比较

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

Feature
自动触发查询请求✔️✔️

允许手动触发查询请求

✔️✔️✔️✔️✔️

允许手动触发变更请求

✔️

订阅一个组件以在存储中保持缓存数据

✔️✔️✔️✔️✔️

返回请求状态和来自存储的缓存数据

✔️✔️✔️✔️

当请求状态和数据可用时重新渲染

✔️✔️✔️✔️

接受轮询/重新获取选项以触发自动重新获取

✔️✔️✔️✔️

useQuery

访问 useQuery hook
const useQueryResult = api.endpoints.getPosts.useQuery(arg, options)
// 或者
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> = {
// 基础查询状态
originalArgs?: unknown // 传递给查询的参数
data?: T // 如果存在,返回最新的结果,无论 hook arg 如何
currentData?: T // 如果存在,返回当前 hook arg 的最新结果
error?: unknown // 如果存在,返回错误结果
requestId?: string // 由 RTK Query 生成的字符串
endpointName?: string // 查询的端点名称
startedTimeStamp?: number // 查询启动的时间戳
fulfilledTimeStamp?: number // 查询完成的时间戳

// 派生的请求状态布尔值
isUninitialized: boolean // 查询尚未开始。
isLoading: boolean // 查询正在首次加载。还没有数据。
isFetching: boolean // 查询正在获取,但可能有来自早期请求的数据。
isSuccess: boolean // 查询有来自成功加载的数据。
isError: boolean // 查询当前处于"错误"状态。

refetch: () => QueryActionCreatorResult // 强制重新获取查询的函数 - 返回带有附加方法的 Promise
}
  • 参数
    • arg: 用于构造查询本身的查询参数,并作为查询的缓存键。 你也可以在这里传入 skipToken 作为跳过查询的另一种方式,参见 skipToken
    • options: 控制 hook 获取行为的一组选项
  • 返回
    • 一个查询结果对象,包含当前的加载状态,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 hook
const useMutationResult = api.endpoints.updatePost.useMutation(options)
// 或者
const useMutationResult = api.useUpdatePostMutation(options)

签名

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

type UseMutationStateOptions = {
// 一种确定 `UseMutationResult` 内容的方法
selectFromResult?: (result: UseMutationStateDefaultResult) => any
// 一个字符串,用于在具有相同键的 hook 实例之间启用共享结果
fixedCacheKey?: string
}

type UseMutationTrigger<T> = (arg: any) => Promise<
{ data: T } | { error: BaseQueryError | SerializedError }
> & {
requestId: string // 由 RTK Query 生成的字符串
abort: () => void // 取消 mutation promise 的方法
unwrap: () => Promise<T> // 解包 mutation 调用并提供原始响应/错误的方法
reset: () => void // 手动取消订阅 mutation 调用并将结果重置为未初始化状态的方法
}

type UseMutationResult<T> = {
// 基础查询状态
originalArgs?: unknown // 传递给最新 mutation 调用的参数。如果使用 `fixedCacheKey` 选项,则不可用
data?: T // 如果存在,返回结果
error?: unknown // 如果存在,返回错误结果
endpointName?: string // mutation 的端点名称
fulfilledTimestamp?: number // mutation 完成的时间戳

// 派生的请求状态布尔值
isUninitialized: boolean // Mutation 还未触发
isLoading: boolean // Mutation 已触发并正在等待响应
isSuccess: boolean // Mutation 有来自成功调用的数据
isError: boolean // Mutation 当前处于"错误"状态
startedTimeStamp?: number // 最新 mutation 启动的时间戳

reset: () => void // 手动取消订阅 mutation 调用并将结果重置为未初始化状态的方法
}
提示

生成的 UseMutation hook 默认会在触发回调被触发后导致组件重新渲染,因为它影响了结果的属性。如果你想调用触发器,但不关心用 hook 订阅结果,你可以使用 selectFromResult 选项来限制 hook 关心的属性。

返回一个完全空的对象将意味着任何单个 mutation 调用最多只会导致一次重新渲染,例如:

selectFromResult: () => ({})
  • 参数

    • options:一组控制钩子订阅行为的选项:
      • selectFromResult:可用于自定义作为元组第二项返回的变异结果的回调
      • fixedCacheKey:用于在钩子实例之间共享结果的可选字符串
  • 返回:包含以下内容的元组:

    • trigger:一个基于提供的参数更新数据的函数。触发函数返回一个带有上述属性的 promise,可以用来处理 promise 的行为
    • mutationState:包含当前加载状态和请求的元数据的查询状态对象,或者适用时,由 selectFromResult 选项返回的值。 此外,此对象将包含
      • 一个 reset 方法,用于将钩子重置回其原始状态并从缓存中删除当前结果
      • 一个 originalArgs 属性,包含传递给 trigger 函数最后一次调用的参数。

描述

一个React钩子,它让你触发给定端点的更新请求,并让组件订阅从Redux存储中读取请求状态。当加载状态改变时,组件将重新渲染。

特性

  • 手动控制触发请求以更改服务器上的数据或可能使缓存失效
  • '订阅' 组件以保持缓存数据在存储中,并在组件卸载时 '取消订阅'
  • 从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> = {
// 基础查询状态
originalArgs?: unknown // 传递给查询的参数
data?: T // 最新返回的结果,无论钩子参数如何,如果存在
currentData?: T // 当前钩子参数的最新返回结果,如果存在
error?: unknown // 如果存在,错误结果
requestId?: string // 由 RTK Query 生成的字符串
endpointName?: string // 查询的给定端点的名称
startedTimeStamp?: number // 查询启动时的时间戳
fulfilledTimeStamp?: number // 查询完成时的时间戳

isUninitialized: false // 查询尚未开始。
isLoading: false // 查询正在首次加载。还没有数据。
isFetching: false // 查询正在获取,但可能有来自早期请求的数据。
isSuccess: false // 查询有来自成功加载的数据。
isError: false // 查询当前处于“错误”状态。
}
  • 参数

    • arg:传递给端点中定义的查询的参数。 你也可以在这里作为跳过选择的另一种方式传入 skipToken,参见 skipToken
    • options:一组控制钩子返回值的选项
  • 返回

    • 包含当前加载状态、API 调用返回的实际数据或错误以及关于请求的元数据的查询结果对象。可以用 selectFromResult 进行自定义

描述

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

注意,这个钩子不会触发获取新数据。对于这种用例,请查看 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 // 一个强制重新获取查询的函数
}
  • 参数

    • arg:传递给端点中定义的查询的参数。 你也可以在这里作为跳过查询的另一种方式传入 skipToken,参见 skipToken
    • options:一组控制钩子获取行为的选项
  • 返回

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

描述

一个 React 钩子,它自动触发从端点获取数据,并将组件 '订阅' 到缓存数据。

查询参数被用作缓存键。改变查询参数将告诉钩子如果数据在缓存中不存在则重新获取数据。

注意,这个钩子不返回请求状态或缓存数据。对于这种用例,请查看 useQueryuseQueryState

特性

  • 根据钩子参数和是否存在缓存数据,默认自动触发请求以检索数据
  • '订阅' 组件以保持缓存数据在存储中,并在组件卸载时 '取消订阅'
  • 接受轮询/重新获取选项,当满足相应条件时触发自动重新获取

useLazyQuery

访问 useLazyQuery 钩子
const [trigger, result, lastPromiseInfo] =
api.endpoints.getPosts.useLazyQuery(options)
// 或
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 // 提供给查询的参数
requestId: string // 由 RTK Query 生成的字符串
subscriptionOptions: SubscriptionOptions // 用于查询订阅的值
abort: () => void // 取消查询承诺的方法
unwrap: () => Promise<T> // 解开查询调用并提供原始响应/错误的方法
unsubscribe: () => void // 用于手动取消订阅查询结果的方法
refetch: () => void // 用于重新运行查询的方法。在大多数使用懒查询的情况下,你永远不会使用这个,应该优先调用触发器。
updateSubscriptionOptions: (options: SubscriptionOptions) () => void // 用于更新订阅选项(例如,pollingInterval)的方法
}

type UseQueryStateResult<T> = {
// 基本查询状态
originalArgs?: unknown // 传递给查询的参数
data?: T // 如果存在,无论触发器参数如何,最新返回的结果
currentData?: T // 如果存在,触发器参数的最新返回结果
error?: unknown // 如果存在,错误结果
requestId?: string // 由 RTK Query 生成的字符串
endpointName?: string // 查询的给定端点的名称
startedTimeStamp?: number // 查询启动的时间戳
fulfilledTimeStamp?: number // 查询完成的时间戳

isUninitialized: false // 查询尚未开始。
isLoading: false // 查询正在首次加载。还没有数据。
isFetching: false // 查询正在获取,但可能有来自早期请求的数据。
isSuccess: false // 查询有来自成功加载的数据。
isError: false // 查询当前处于“错误”状态。
}

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 =
| {
// 如果指定,只有当 `new Date()` 和最后一个
// `fulfilledTimeStamp` 之间的差值大于给定值(以秒为单位)时,才会运行查询
ifOlderThan?: false | number
}
| {
// 如果 `force: true`,它将忽略 `ifOlderThan` 值(如果设置),并且即使查询存在于缓存中,也会运行查询。
force?: boolean
}

type PrefetchCallback = (arg: any, options?: UsePrefetchOptions) => void
  • 参数

    • endpointName: 要预获取数据的端点名称
    • options: 控制是否应发生预获取请求的一组选项
  • 返回

    • 当被调用时,将开始获取提供的端点的数据的 prefetch 回调

描述

一个可以用来提前获取数据的 React 钩子。

特性

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