跳到主要内容

 

API 切片:实用工具

API 切片对象包含可以用于缓存管理的各种实用工具, 例如实现乐观更新, 以及实现服务器端渲染

这些都包含在 API 对象的 api.util 中。

信息

此页面上的一些 TS 类型是伪代码,用于说明意图,因为实际的内部类型相当复杂。

updateQueryData

签名

const updateQueryData = (
endpointName: string,
args: any,
updateRecipe: (draft: Draft<CachedState>) => void,
updateProvided?: boolean,
) => ThunkAction<PatchCollection, PartialState, any, AnyAction>

interface PatchCollection {
patches: Patch[]
inversePatches: Patch[]
undo: () => void
}
  • 参数
    • endpointName:与现有端点名称匹配的字符串
    • args:与之前查询调用使用的参数匹配,用于确定需要更新哪个缓存数据集
    • updateRecipe:一个 Immer produce 回调,可以将更改应用于缓存状态
    • updateProvided:一个布尔值,表示是否应根据更新的缓存重新计算端点的提供的标签。默认为 false

描述

一个 Redux thunk 动作创建器,当调度时,创建并应用一组 JSON 差异/补丁对象到当前状态。这立即用这些更改更新 Redux 状态。

thunk 动作创建器接受三个参数:我们正在更新的端点的名称(如 'getPost')、任何相关的查询参数和一个回调函数。回调接收当前状态的 Immer 包装的 draft,并可能修改 draft 以匹配突变成功完成后的预期结果。

thunk 返回一个包含 {patches: Patch[], inversePatches: Patch[], undo: () => void} 的对象。patchesinversePatches 是使用 Immer 的 produceWithPatches 方法生成的。

这通常用作实现乐观更新的第一步。生成的 inversePatches 可以用于通过调用 dispatch(patchQueryData(endpointName, args, inversePatches)) 来撤销更新。或者,可以直接调用 undo 方法以达到相同的效果。

请注意,前两个参数(endpointNameargs)用于确定要更新哪个现有的缓存条目。如果找不到现有的缓存条目,updateRecipe 回调将不会运行。

示例 1

const patchCollection = dispatch(
api.util.updateQueryData('getPosts', undefined, (draftPosts) => {
draftPosts.push({ id: 1, name: 'Teddy' })
}),
)

在上面的示例中,'getPosts' 是为 endpointName 提供的,undefined 是为 args 提供的。这将匹配查询缓存键 'getPosts(undefined)'

即,它将匹配可能已经通过以下任何调用创建的缓存条目:

api.endpoints.getPosts.useQuery()

useGetPostsQuery()

useGetPostsQuery(undefined, { ...options })

dispatch(api.endpoints.getPosts.initiate())

dispatch(api.endpoints.getPosts.initiate(undefined, { ...options }))

示例 2

const patchCollection = dispatch(
api.util.updateQueryData('getPostById', 1, (draftPost) => {
draftPost.name = 'Lilly'
}),
)

在上面的示例中,'getPostById' 是为 endpointName 提供的,1 是为 args 提供的。这将匹配查询缓存键 'getPostById(1)'

即,它将匹配可能已经通过以下任何调用创建的缓存条目:

api.endpoints.getPostById.useQuery(1)

useGetPostByIdQuery(1)

useGetPostByIdQuery(1, { ...options })

dispatch(api.endpoints.getPostById.initiate(1))

dispatch(api.endpoints.getPostById.initiate(1, { ...options }))

upsertQueryData

签名

const upsertQueryData = <T>(endpointName: string, args: any, newEntryData: T) =>
ThunkAction<Promise<CacheEntry<T>>, PartialState, any, UnknownAction>
  • 参数
    • endpointName:与现有端点名称匹配的字符串
    • args:与之前查询调用使用的参数匹配,用于确定需要更新哪个缓存数据集
    • newEntryValue:要写入相应缓存条目的 data 字段的值

描述

一个 Redux thunk 动作创建器,当调度时,作为一个人工 API 请求来插入或更新缓存中的值。

thunk 动作创建器接受三个参数:我们正在更新的端点的名称(如 'getPost')、用于构造所需缓存键的适当查询参数值,以及要插入的数据。

如果该缓存键不存在缓存条目,将创建一个缓存条目并添加数据。如果缓存条目已经存在,这将 覆盖 现有的缓存条目数据。

thunk 异步 执行,并返回一个在存储已更新时解析的 promise。

如果在实际请求进行中调度,那么一旦它们解析,将处理 upsert 和请求,从而导致 "最后结果获胜" 的更新行为。

示例

await dispatch(
api.util.upsertQueryData('getPost', { id: 1 }, { id: 1, text: 'Hello!' }),
)

patchQueryData

签名

const patchQueryData = (
endpointName: string,
args: any,
patches: Patch[],
updateProvided?: boolean
) => ThunkAction<void, PartialState, any, UnknownAction>;
  • 参数
    • endpointName:与现有端点名称匹配的字符串
    • args:缓存键,用于确定需要更新哪个缓存数据集
    • patches:要应用于缓存状态的补丁数组(或逆补丁)。这些通常是从调度 updateQueryData 的结果中获取的
    • updateProvided:一个布尔值,表示是否应根据更新的缓存重新计算端点的提供的标签。默认为 false

描述

一个 Redux thunk 动作创建器,当调度时,将 JSON 差异/补丁数组应用于给定查询结果的缓存数据。这立即用这些更改更新 Redux 状态。

thunk 动作创建器接受三个参数:我们正在更新的端点的名称(如 'getPost')、用于构造所需缓存键的适当查询参数值,以及由 Immer 的 produceWithPatches 生成的 JSON 差异/补丁数组。

这通常用作实现乐观更新的第二步。如果请求失败,可以通过调度 patchQueryData 并使用 updateQueryData 之前生成的 inversePatches 来撤销乐观地应用的更改。

在希望简单地撤销之前的更改的情况下,可能更倾向于调用从调度 updateQueryData 返回的 undo 方法。

示例

const patchCollection = dispatch(
api.util.updateQueryData('getPosts', undefined, (draftPosts) => {
draftPosts.push({ id: 1, name: 'Teddy' })
}),
)

// later
dispatch(
api.util.patchQueryData(
'getPosts',
undefined,
patchCollection.inversePatches,
),
)

// or
patchCollection.undo()

prefetch

签名

type PrefetchOptions = { ifOlderThan?: false | number } | { force?: boolean }

const prefetch = (endpointName: string, arg: any, options: PrefetchOptions) =>
ThunkAction<void, any, any, UnknownAction>
  • 参数
    • endpointName:与现有端点名称匹配的字符串
    • args:缓存键,用于确定需要更新哪个缓存数据集
    • options:确定在给定情况下是否应发送请求的选项:
      • ifOlderThan:如果指定,只有当 new Date() 和最后的 fulfilledTimeStamp 之间的差值大于给定值(以秒为单位)时,才会运行查询
      • force:如果为 true,它将忽略设置的 ifOlderThan 值,即使查询存在于缓存中,也会运行查询。

描述

一个 Redux thunk 动作创建器,可以用于手动触发数据的预获取。

thunk 动作创建器接受三个参数:我们正在更新的端点的名称(如 'getPost')、任何相关的查询参数,以及一组选项,用于确定是否应根据缓存的陈旧性重新获取数据。

React Hooks 用户最可能永远不需要直接使用这个,因为 usePrefetch 钩子将在需要时内部调度 thunk 动作创建器的结果,当你调用钩子提供的预获取函数时。

示例

dispatch(api.util.prefetch('getPosts', undefined, { force: true }))

selectInvalidatedBy

签名

function selectInvalidatedBy(
state: RootState,
tags: ReadonlyArray<TagDescription<string>>,
): Array<{
endpointName: string
originalArgs: any
queryCacheKey: QueryCacheKey
}>
  • 参数
    • state:根状态
    • tags:一个只读的无效标签数组,其中提供的 TagDescription 是提供给 api 的 tagTypes 属性的字符串之一。例如:
      • [TagType]
      • [{ type: TagType }]
      • [{ type: TagType, id: number | string }]

描述

一个可以选择要使其无效的查询参数的函数。

该函数接受两个参数

  • 根状态和
  • 要使其无效的缓存标签。

它返回一个数组,其中包含

  • 端点名称,
  • 原始参数和
  • 查询缓存键。

示例

const entries = api.util.selectInvalidatedBy(state, ['Post'])
const entries = api.util.selectInvalidatedBy(state, [{ type: 'Post', id: 1 }])
const entries = api.util.selectInvalidatedBy(state, [
{ type: 'Post', id: 1 },
{ type: 'Post', id: 4 },
])

invalidateTags

签名

const invalidateTags = (
tags: Array<TagTypes | FullTagDescription<TagTypes>>,
) => ({
type: string,
payload: tags,
})
  • 参数
    • tags:要失效的标签数组,其中提供的 TagType 是提供给 api 的 tagTypes 属性的字符串之一。例如:
      • [TagType]
      • [{ type: TagType }]
      • [{ type: TagType, id: number | string }]

描述

一个 Redux 动作创建器,可以用于手动使缓存标签失效,以进行自动重新获取

动作创建器接受一个参数:要失效的缓存标签。它返回一个动作,其中包含这些标签作为有效载荷,以及 api 的相应 invalidateTags 动作类型。

调度此动作创建器的结果将使给定的标签失效,如果它们订阅了提供相应标签的缓存数据,将导致查询自动重新获取。

示例

dispatch(api.util.invalidateTags(['Post']))
dispatch(api.util.invalidateTags([{ type: 'Post', id: 1 }]))
dispatch(
api.util.invalidateTags([
{ type: 'Post', id: 1 },
{ type: 'Post', id: 'LIST' },
]),
)

selectCachedArgsForQuery

签名

function selectCachedArgsForQuery(
state: RootState,
queryName: QueryName,
): Array<QueryArg>
  • 参数
    • state:根状态
    • queryName:与现有查询端点名称匹配的字符串

描述

一个可以选择当前缓存查询的参数的函数。

该函数接受两个参数

  • 根状态和
  • 查询的名称

它返回一个数组,其中包含每个条目使用的参数。

示例

const args = api.util.selectCachedArgsForQuery(state, 'getPosts')

resetApiState

签名

const resetApiState = () => ({
type: string,
payload: undefined,
})

描述

一个 Redux 动作创建器,可以调度以手动完全重置 api 状态。这将立即删除所有现有的缓存条目,所有查询将被视为“未初始化”。

请注意,hooks 也在本地组件状态中跟踪状态,可能不会被 resetApiState 完全重置。

示例

dispatch(api.util.resetApiState())

getRunningQueriesThunkgetRunningMutationsThunk

签名

getRunningQueriesThunk(): ThunkWithReturnValue<Array<QueryActionCreatorResult<any>>>
getRunningMutationsThunk(): ThunkWithReturnValue<Array<MutationActionCreatorResult<any>>>

描述

如果调度,返回所有正在运行的查询或突变的 thunk。 这些返回的值可以像 promise 一样等待。

这对于 SSR 场景非常有用,以等待以任何方式触发的所有查询(或突变),包括通过钩子调用 或手动调度 initiate 动作。

等待所有当前运行的查询示例
await Promise.all(dispatch(api.util.getRunningQueriesThunk()))

getRunningQueryThunkgetRunningMutationThunk

签名

getRunningQueryThunk<EndpointName extends QueryKeys<Definitions>>(
endpointName: EndpointName,
args: QueryArgFrom<Definitions[EndpointName]>
): ThunkWithReturnValue<
| QueryActionCreatorResult<
Definitions[EndpointName] & { type: 'query' }
>
| undefined
>

getRunningMutationThunk<EndpointName extends MutationKeys<Definitions>>(
endpointName: EndpointName,
fixedCacheKeyOrRequestId: string
): ThunkWithReturnValue<
| MutationActionCreatorResult<
Definitions[EndpointName] & { type: 'mutation' }
>
| undefined
>

描述

如果调度,返回给定 端点名称 + 参数(或 requestId/fixedCacheKey)组合的单个正在运行的查询(或突变),如果它当前正在运行。 如果它当前未运行,函数返回 undefined

这些 thunk 主要是为了在未来添加对 suspense 的实验性支持。 它们使编写自定义钩子成为可能,这些钩子查找 RTK Query 是否已经有一个针对某个端点/参数组合的正在运行的查询/突变, 并检索它以将其作为 promise throw