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
:一个 Immerproduce
回调,可以将更改应用于缓存状态updateProvided
:一个布尔值,表示是否应根据更新的缓存重新计算端点的提供的标签。默认为false
。
描述
一个 Redux thunk 动作创建器,当调度时,创建并应用一组 JSON 差异/补丁对象到当前状态。这立即用这些更改更 新 Redux 状态。
thunk 动作创建器接受三个参数:我们正在更新的端点的名称(如 'getPost'
)、任何相关的查询参数和一个回调函数。回调接收当前状态的 Immer 包装的 draft
,并可能修改 draft 以匹配突变成功完成后的预期结果。
thunk 返回一个包含 {patches: Patch[], inversePatches: Patch[], undo: () => void}
的对象。patches
和 inversePatches
是使用 Immer 的 produceWithPatches
方法生成的。
这通常用作实现乐观更新的第一步。生成的 inversePatches
可以用于通过调用 dispatch(patchQueryData(endpointName, args, inversePatches))
来撤销更新。或者,可以直接调用 undo
方法以达到相同的效果。
请注意,前两个参数(endpointName
和 args
)用于确定要更新哪个现有的缓存条目。如果找不到现有的缓存条目,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())
getRunningQueriesThunk
和 getRunningMutationsThunk
签名
getRunningQueriesThunk(): ThunkWithReturnValue<Array<QueryActionCreatorResult<any>>>
getRunningMutationsThunk(): ThunkWithReturnValue<Array<MutationActionCreatorResult<any>>>
描述
如果调度,返回所有正在运行的查询或突变的 thunk。 这些返回的值可以像 promise 一样等待。
这对于 SSR 场景非常有用,以等待以任何方式触发的所有查询(或突变),包括通过钩子调用
或手动调度 initiate
动作。
await Promise.all(dispatch(api.util.getRunningQueriesThunk()))
getRunningQueryThunk
和 getRunningMutationThunk
签名
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
。