You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 20:22:03