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

Next.js中SWR缓存旧数据导致筛选/分页切换显示异常及cache.get()返回undefined的问题求助

Next.js中SWR缓存旧数据导致筛选/分页切换显示异常及cache.get()返回undefined的问题求助

我来帮你梳理下问题出在哪,以及怎么一步步解决:

一、为什么cache.get()总是返回undefined?

你这里的核心问题是SWR缓存的key类型不匹配:

  • 你在useSWR里用的是数组类型的key:["dataRequests", token, currentPage]
  • 但你却把数组转成字符串JSON.stringify(swrKey)去调用cache.get(),而SWR内部缓存是直接用原数组作为key存储的,根本不会识别字符串格式的key,自然返回undefined。

正确的做法是直接用你传给useSWR的原数组去调用cache.get:

const swrKey = token ? ["dataRequests", token, currentPage] : null;
const cachedData = cache.get(swrKey); // 直接传数组key,不要转字符串!

另外要注意:SWR对数组key的匹配是结构相等判断,只要数组元素的内容完全一致,就能匹配到对应的缓存项,不需要额外转格式。


二、你的缓存清除与请求逻辑的问题

你现在的思路是“有缓存就清除,没有就触发请求”,但结合keepPreviousData: true的设置,这个逻辑其实和你想要的效果冲突:

  • keepPreviousData: true的设计初衷是单纯分页切换时保留旧数据,避免页面空白,但如果是筛选/搜索/排序条件变化,你其实不需要保留旧数据,反而要直接加载新数据。
  • 你用GlobalMutate清除缓存的逻辑也有问题:你写的是匹配字符串key,但你的实际key是数组,所以这个过滤条件根本找不到对应的缓存项。

三、正确的解决方案:针对场景优化SWR配置

1. 把所有影响请求结果的参数加入SWR的key

你当前的key只包含了token和currentPage,但筛选条件(filters)、搜索关键词(searchedRequest)、排序规则(sortBy/sortOrder)都是会影响请求结果的参数,必须加入到SWR的key里!不然SWR会把不同筛选条件但同页面/同token的请求当成同一个key,导致缓存完全混乱。

修正后的SWR key应该是这样:

// 把filters转成字符串是因为对象作为数组元素时,结构相等判断会失效(比如两个内容一致的{}会被认为是不同key)
const swrKey = token 
  ? ["dataRequests", token, currentPage, searchedRequest, sortBy, sortOrder, JSON.stringify(filters)] 
  : null;

2. 区分分页和筛选场景,动态设置keepPreviousData

我们可以只在单纯分页切换时保留旧数据,而当筛选/搜索/排序条件变化时,直接加载新数据,不保留旧数据:

// 先判断当前是否是单纯的分页变化(需要你自己维护上一次的参数状态,比如用useRef存上一次的筛选/搜索/排序值)
const prevParamsRef = useRef({ searchedRequest, sortBy, sortOrder, filters: JSON.stringify(filters) });
const isOnlyPageChange = 
  prevParamsRef.current.searchedRequest === searchedRequest &&
  prevParamsRef.current.sortBy === sortBy &&
  prevParamsRef.current.sortOrder === sortOrder &&
  prevParamsRef.current.filters === JSON.stringify(filters);

// 每次渲染更新参数快照
useEffect(() => {
  prevParamsRef.current = { searchedRequest, sortBy, sortOrder, filters: JSON.stringify(filters) };
}, [searchedRequest, sortBy, sortOrder, filters]);

// 然后在SWR配置里动态设置
const { data, mutate, isLoading, isValidating, } = useSWR(
  swrKey,
  () => fetchRequests(
    token, searchedRequest, currentPage, sortBy, sortOrder, filters
  ),
  {
    keepPreviousData: isOnlyPageChange, // 只有单纯分页时才保留旧数据
    dedupingInterval: 500,
  }
);

3. 正确的缓存清除方式

如果你还是需要手动清除缓存并重新请求,不要用cache.get()判断,而是直接用全局mutate匹配正确的key类型:

const { mutate: globalMutate } = useSWRConfig();

// 清除所有和dataRequests相关的缓存(匹配数组key的第一个元素)
globalMutate(
  (key) => Array.isArray(key) && key[0] === "dataRequests",
  undefined,
  { revalidate: false }
);

// 或者更精准:清除当前token下的所有dataRequests缓存
globalMutate(
  (key) => Array.isArray(key) && key[0] === "dataRequests" && key[1] === token,
  undefined,
  { revalidate: false }
);

这里的关键是:你的key是数组,所以在全局mutate的过滤函数里要先判断key是数组,再匹配数组元素,而不是去匹配字符串。


四、其他需要注意的细节

  1. 你同时使用了useSWR返回的mutate和全局的GlobalMutate,建议统一命名(比如把全局的叫globalMutate),避免变量名冲突导致逻辑混乱。
  2. 不要在组件渲染根节点直接调用cache.get()和mutate,这会导致每次组件渲染都执行该逻辑,引发不必要的重渲染和请求,建议把逻辑放到useEffect里,结合状态变化触发。

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.08 14:29:29