我有一个轮播组件,它使用 Redux-Toolkit Query (RTKQ) 获取 8 个项目,而侧边栏上的另一个组件也使用 RTKQ 获取 3 个项目。它们同时渲染,并且使用相同的 RTKQ,有时,存在一个错误,使它们共享相同数量的项目(虽然它们不应该)
他们都使用这个查询。
const { data } = useGetPopularClipsQuery({ limit: 3, page: 1 });
const { data } = useGetPopularClipsQuery({ limit: 8, page: 0 });
RTKQ
getPopularClips: builder.query<
{ posts: Array<Post>; hasMore: boolean },
{ limit?: number; page: number }
>({
providesTags: ['PopularClips'],
query: ({ limit = 5, page }) => ({
url: `/post/popular-clips`,
params: {
limit,
page
}
}),
transformResponse(baseQueryReturnValue: Post[], meta, arg) {
return {
posts: baseQueryReturnValue.map((clip) => ({
...clip,
...arg,
fromQuery: `getPopularClips`
})),
hasMore: baseQueryReturnValue.length > 0havr
};
},
serializeQueryArgs: ({ endpointName }) => endpointName,
merge: (currentCache, newItems) => ({
posts: uniqBy(
[...currentCache.posts, ...newItems.posts],
(clip) => clip.id
),
hasMore: newItems.posts.length > 0
}),
forceRefetch: ({ currentArg, previousArg }) =>
currentArg?.page !== previousArg?.page
}),
两个组件必须同时渲染,但它们应该具有不同数量的项目。
您对所有订阅使用相同的查询缓存键,即端点名称。
serializeQueryArgs: ({ endpointName }) => endpointName,
通常,您不指定
serializeQueryArgs
并让defaultSerializeQueryArgs
函数处理它,这会创建一个缓存键,该键是端点名称和查询参数的字符串化版本的组合。
从
serializeQueryArgs
端点删除 getPopularClips
将允许使用 page
和 limit
参数创建缓存条目。如果两个(或任何重复的)参数集在两个或多个钩子调用中使用,那么它们将仍然共享一个缓存条目,因为缓存键将解析为相同。
如果由于某种原因您仍然希望单独缓存具有重复查询参数的单独查询挂钩,那么我建议添加另一个参数。
示例:
getPopularClips: builder.query<
{ posts: Array<Post>; hasMore: boolean },
{ id?: string; limit?: number; page: number }
>({
providesTags: ['PopularClips'],
query: ({ limit = 5, page }) => ({
url: `/post/popular-clips`,
params: {
limit,
page
}
}),
transformResponse(baseQueryReturnValue: Post[], meta, arg) {
return {
posts: baseQueryReturnValue.map((clip) => ({
...clip,
...arg,
fromQuery: `getPopularClips`
})),
hasMore: baseQueryReturnValue.length > 0havr
};
},
merge: (currentCache, newItems) => ({
posts: uniqBy(
[...currentCache.posts, ...newItems.posts],
(clip) => clip.id
),
hasMore: newItems.posts.length > 0
}),
forceRefetch: ({ currentArg, previousArg }) =>
currentArg?.page !== previousArg?.page
}),
const { data } = useGetPopularClipsQuery({ id: "hook1", limit: 3, page: 1 });
const { data } = useGetPopularClipsQuery({ id: "hook2", limit: 3, page: 1 });