我有 3 个类别的 3 个按钮,它们是 1.查看所有 2.手机 3.笔记本电脑,当单击每个类别时,它会加载与之相关的列表,而且我正在尝试实现 分页。 我正在使用 React 和 Redux 工具包/RTK 查询。
以下是使用状态及查询
const [currentPage, setCurrentPage] = useState(1);
const [category, setCategory] = useState('all');
const {
data ,
isLoading,
isFetching ,
error
} = useCategorySearchAPIQuery(
{groupBy: selectedCategory, page: currentPage},
{refetchOnMountOrArgChange: true},
);
下面是构建器查询,其中 groupBy 是所选类别
categorySearchAPI: builder.query({
query: ({groupBy, page}) => ({
url: `${CATEGORY_ENDPOINT}/all?group_by=${groupBy}&page=${page}`,
}),
transformResponse: (response, meta, arg) => {
return response.data;
},
serializeQueryArgs: ({endpointName}) => {
return endpointName;
},
// Always merge incoming data to the cache entry
merge: (currentCache, newItems) => {
currentCache.push(...newItems);
},
// Refetch when the page arg changes
forceRefetch({currentArg, previousArg}) {
return currentArg !== previousArg;
},
}),
所需的流程是,当单击类别按钮时,它应该仅显示单击的类别,并且当滚动时,它应该加载该类别的下一页。当类别更改时,会使用新数据重置缓存。
当前当类别更改时 - 数据不会重置并且会混合(类别会混合)。我需要在类别更改时重置并在滚动时增加页面。
在搜索解决方案后发现此代码设置但无法使其按预期工作。这里出了什么问题。
要轻松解决此问题,您必须在
category
中包含 serializeQueryArgs
参数:
serializeQueryArgs: ({
endpointName,
queryArgs,
endpointDefinition,
}) => {
const { groupBy } = queryArgs;
return defaultSerializeQueryArgs({
endpointName,
queryArgs: { groupBy },
endpointDefinition,
});
},
这会为每个类别创建一个缓存,因为
category
现在是缓存键定义的一部分。因此从技术上讲,您不会重置缓存数据,而是会更改您指向的缓存。然后如果用户快速按下之前的类别,数据就会在那里。
使用
forceRefetch
或refetchOnMountOrArgChange
,因为您正在重复代码。
使用乐观更新
updateQueryData
以防您删除/更新缓存中的对象。
在这里你有一个很好的
merge
功能:
export function mergeData<T extends ListResponseTypes>(
currentCacheData: BaseListResponseFor<T>,
responseData: BaseListResponseFor<T>,
customOrder: boolean | undefined = false
) {
if (responseData?.pagination?.prev_page && responseData?.items?.length <= 0) {
return currentCacheData;
}
if (
isNil(responseData?.pagination?.prev_page) &&
isNil(responseData?.pagination?.next_page)
) {
return { pagination: responseData?.pagination, items: responseData?.items };
}
// Create a map for efficient lookups of existing entities
const currentDataMap = new Map<number, T>();
// Populate the map with existing entities based on their IDs
for (const entity of currentCacheData.items) {
currentDataMap.set(entity.id, entity);
}
// Iterate through each entity in the new data https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/set
for (const newEntity of responseData.items) {
currentDataMap.set(newEntity.id, newEntity);
}
// Create a new array to store the result
const updatedData = customOrder
? [...currentDataMap.values()]
: [...currentDataMap.values()]?.sort(
(a, b) =>
new Date(b.created_at).getTime() - new Date(a.created_at).getTime()
);
return { pagination: responseData?.pagination, items: updatedData };
}