使用useSWRInfinite hook时,如何在带查询参数的API中修改缓存?
useSWRInfinite带查询参数时全局mutate失效的解决思路
核心原因
useSWRInfinite的缓存键基于每次请求的唯一标识生成,若以带查询参数的字符串作为缓存键,容易出现参数顺序不一致、编码差异等问题,导致全局mutate无法匹配对应缓存;同时,全局mutate的默认匹配逻辑可能无法识别结构化缓存键。
具体解决步骤
1. 改用结构化缓存键替代字符串URL
不要直接返回带查询参数的字符串,而是返回包含基础路径和参数对象的数组,让SWR内部统一序列化缓存键,避免参数顺序或编码导致的不匹配:
const getKey = (pageIndex, previousPageData) => { // 无更多数据时返回null,终止请求 if (previousPageData && !previousPageData.hasNext) return null; // 结构化缓存键:基础路径 + 参数对象 return ['/api/your-data-endpoint', { page: pageIndex + 1, keyword: currentKeyword, category: activeCategory }]; }; const { data, setSize } = useSWRInfinite(getKey, yourFetcherFunction);
2. 全局mutate时使用缓存键匹配逻辑
全局更新时,不要传字符串URL,而是用匹配函数精准定位所有相关缓存:
// 匹配所有以'/api/your-data-endpoint'为基础路径的缓存 mutate((cacheKey) => { return Array.isArray(cacheKey) && cacheKey[0] === '/api/your-data-endpoint'; });
若需针对特定参数的缓存更新,可直接传入结构化键:
// 更新所有keyword为currentKeyword的缓存 mutate(['/api/your-data-endpoint', { keyword: currentKeyword }]);
3. 统一字符串URL的参数生成规则
如果必须使用字符串作为缓存键,确保所有生成URL的地方用统一的参数序列化工具(如qs.stringify),保证参数顺序和编码完全一致:
import qs from 'qs'; const getKey = (pageIndex, previousPageData) => { if (previousPageData && !previousPageData.hasNext) return null; const params = { page: pageIndex + 1, keyword: currentKeyword }; // 用统一工具序列化参数,强制排序避免顺序差异 return `/api/your-data-endpoint?${qs.stringify(params, { sort: true })}`; };
4. 手动管理缓存(进阶方案)
通过SWR的缓存实例直接操作,适合复杂场景:
import { useSWRConfig } from 'swr'; // 获取全局缓存实例 const { cache } = useSWRConfig(); const updateAllRelatedData = () => { // 遍历缓存键,匹配后触发更新 for (const key of cache.keys()) { if (Array.isArray(key) && key[0] === '/api/your-data-endpoint') { cache.delete(key); // 删除旧缓存 mutate(key); // 触发重新请求 } } };
内容的提问来源于stack exchange,提问作者Ganesh Lamichhane
相关产品推荐
相关产品推荐

