使用RTKQuery实现无限滚动遇缓存问题,求组件卸载时清理缓存方案
解决RTK Query无限滚动的缓存冲突与组件卸载时清理缓存问题
问题分析
你当前的serializeQueryArgs仅返回端点名称,导致所有分页请求共享同一个缓存键。当组件卸载再返回后,page重置为1,新请求的结果会和之前缓存的所有分页数据合并,引发重复key等问题;而错误修改serializeQueryArgs又会导致缓存无法复用或被直接清空。
解决方案
1. 修正缓存键逻辑(优先方案)
先修复serializeQueryArgs,让同规格的分页请求共享缓存,不同规格的请求区分缓存,同时保留无限滚动的合并逻辑:
serializeQueryArgs: ({ queryArgs, endpointName }) => { // 基于size分组缓存,若你的场景中size可能动态变化,必须将size纳入缓存键 return `${endpointName}-${queryArgs.size}`; },
这样同一size下的分页请求会共享缓存,切换页面返回后,若size不变,page=1的请求会触发重新请求并覆盖原有缓存(forceRefetch逻辑会判断page变化),避免旧数据残留。
2. 组件卸载时清理指定缓存
如果需要在组件卸载时完全清理该端点的缓存,可在组件中结合useEffect和RTK Query的工具函数实现:
import { useDispatch } from '@reduxjs/toolkit'; import { fetchUsers } from './yourApiSlice'; function UserList() { const dispatch = useDispatch(); const { data, fetchNextPage } = useFetchUsersQuery({ page: 1, size: 10 }); // 组件卸载时执行缓存清理 useEffect(() => { return () => { // 清空该端点的所有缓存与订阅 dispatch(fetchUsers.util.resetApiState()); // 若只需清除当前组件使用的特定参数缓存,可使用: // dispatch(fetchUsers.util.removeQuerySubscription({ page: 1, size: 10 })); }; }, [dispatch]); // 无限滚动相关逻辑... }
3. 调整merge逻辑避免重复数据
如果需要保留原有缓存键逻辑,可在merge阶段添加去重处理,避免重复数据导致的key冲突:
merge: (currentCache, newCache) => { const existingUserIds = new Set(currentCache.users.map(user => user.id)); currentCache.users.push(...newCache.users.filter(user => !existingUserIds.has(user.id))); },
补充注意
- 禁止将
serializeQueryArgs返回固定值,这会导致所有请求共用同一缓存,极易引发数据混乱 - 你当前的
forceRefetch逻辑是正确的,能确保不同page的请求会重新发起
内容的提问来源于stack exchange,提问作者kvaizer999
相关产品推荐
相关产品推荐

