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

SWR:如何高效处理筛选场景?

在SWR中处理多作者书籍请求的缓存优化方案

这个问题确实是SWR使用中很常见的缓存优化场景,核心痛点就是避免重复获取已有数据、最大化复用缓存。我来分享几个实用的解决思路:

1. 拆分请求维度,按单个作者独立缓存

不要把包含多个作者的完整URL作为唯一缓存键,而是把每个作者的请求拆分开,让SWR分别缓存每个作者的书籍数据。这样新增作者时只请求新数据,切换单个作者时直接复用已有缓存:

// 封装单个作者的书籍请求函数
const fetchBooksByAuthor = async (author) => {
  const res = await fetch(`example.com/books?author[]=${author}`);
  return res.json();
};

// 针对每个需要的作者单独使用SWR,缓存键用数组标识更清晰
const { data: tolkienBooks } = useSWR(['author', 'tolkien'], () => fetchBooksByAuthor('tolkien'));
const { data: shakespeareBooks } = useSWR(['author', 'shakespeare'], () => fetchBooksByAuthor('shakespeare'));

// 新增罗琳的书籍时,只新增这一个SWR实例,不会重复请求已有作者的数据
const { data: rowlingBooks } = useSWR(['author', 'rowling'], () => fetchBooksByAuthor('rowling'));

// 在客户端合并所有需要的书籍数据
const combinedBooks = [
  ...(tolkienBooks || []),
  ...(shakespeareBooks || []),
  ...(rowlingBooks || [])
];

这种方式完全贴合SWR的缓存设计理念,每个作者的数据独立存储,复用性极强,后续不管是新增、移除作者,都不会产生冗余请求。

2. 使用mutate手动合并缓存数据

如果业务上必须使用包含多个作者的合并请求URL,可以通过SWR的mutate方法手动更新缓存,避免重新请求全量数据:

// 初始请求的缓存键和数据
const initialAuthors = ['tolkien', 'shakespeare'];
const cacheKey = `example.com/books?author[]=${initialAuthors.join('&author[]=')}`;
const { data: initialBooks, mutate } = useSWR(cacheKey, fetchBooks);

// 新增作者的函数
const addNewAuthor = async (newAuthor) => {
  // 先单独请求新作者的书籍数据
  const newAuthorBooks = await fetch(`example.com/books?author[]=${newAuthor}`).then(res => res.json());
  
  // 手动更新缓存:把新数据合并到现有缓存中,第二个参数false表示不触发重新请求
  mutate(prevData => [...(prevData || []), ...newAuthorBooks], false);
  
  // 如果之后需要让缓存和服务器同步,可以在合适时机调用mutate()(不带参数)触发重验证
};

当你调用addNewAuthor('rowling')时,只会请求罗琳的书籍,然后直接合并到原缓存里,不会重复拉取托尔金和莎士比亚的数据。

3. 控制重验证选项,避免重复请求已有缓存

当切换回单个作者的请求时,如果该作者的数据已经在缓存中,可以通过SWR的配置选项关闭自动重验证,直接复用缓存:

const { data: tolkienBooks } = useSWR(
  'example.com/books?author[]=tolkien',
  fetchBooks,
  {
    revalidateIfStale: false, // 缓存未过期时,不自动重新验证
    revalidateOnMount: false, // 组件挂载时不触发重验证,直接用缓存
    // 可以搭配cacheTime设置缓存过期时间,比如cacheTime: 3600000(1小时)
  }
);

这个方法适合数据更新频率不高的场景,如果数据可能频繁变动,记得在需要时手动调用mutate()触发重验证,保证数据新鲜度。

4. 自定义缓存存储,实现智能请求合并

如果需要更灵活的缓存策略,可以自定义SWR的缓存存储(比如用Map),在请求前先检查缓存中已有哪些作者的数据,只请求缺失的部分,再合并结果:

// 自定义缓存,按作者名存储书籍数据
const authorCache = new Map();

// 封装合并请求的fetch函数
const fetchCombinedBooks = async (authors) => {
  // 筛选出缓存中没有的作者
  const missingAuthors = authors.filter(author => !authorCache.has(author));
  
  if (missingAuthors.length > 0) {
    // 只请求缺失作者的数据
    const newBooks = await fetch(`example.com/books?author[]=${missingAuthors.join('&author[]=')}`).then(res => res.json());
    
    // 将新数据按作者分类存入缓存
    missingAuthors.forEach(author => {
      authorCache.set(author, newBooks.filter(book => book.author === author));
    });
  }
  
  // 从缓存中合并所有需要的作者数据
  return authors.flatMap(author => authorCache.get(author) || []);
};

// 使用自定义fetch函数,缓存键用作者数组标识
const { data: combinedBooks } = useSWR(['combined-authors', authors], () => fetchCombinedBooks(authors));

这种方式既保留了合并请求的灵活性,又最大化复用了已有缓存,适合复杂的多维度筛选场景。


内容的提问来源于stack exchange,提问作者Marnix.hoh

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.27 13:07:35