如何利用SWR Hook缓存数据并避免自动重复请求
解决SWR缓存复用与无效请求问题
我来帮你梳理下问题并给出针对性的解决方案,你的核心需求有两个:一是重新导航到组件时复用SWR缓存、避免重复请求;二是彻底阻止SWR的自动重发请求,消除无效的404请求。咱们一步步调整你的代码:
核心问题分析
你之前的代码有两个关键误区:
- 错误地将SWR的配置项(比如
revalidateOnFocus)放到了parameters状态中,这些配置应该作为useSWR的第三个参数传入,而非请求Key的一部分; - 用
mounted状态切换请求Key为null的逻辑,会导致SWR频繁触发无效请求,同时也不利于缓存匹配。
修改后的完整代码
const CategoryList = ({ setLoading }) => { const [category, setCategory] = useState(''); const company_id = localStorage.getItem('company_id'); const session = new SessionService(); // 定义稳定的请求Key:仅当company_id存在时生成有效URL,确保导航回来时能匹配缓存 const swrKey = company_id ? `${session.domain}/company/${company_id}/category-stats` : null; const { data: dataFromFetch, error } = useSWR(swrKey, (url) => session.fetch(url, { method: 'GET' }), { // 彻底禁用所有自动重验证行为 revalidateOnFocus: false, revalidateOnMount: false, // 挂载时直接用缓存,不发起新请求 revalidateOnReconnect: false, refreshWhenOffline: false, refreshWhenHidden: false, refreshInterval: 0, // 关闭定时刷新 onSuccess: (data) => { setCategory(data); setLoading(false); }, onError: (err) => { console.log("error", err); setLoading(false); } } ); // 组件挂载时初始化loading状态 useEffect(() => { setLoading(true); // 若已有缓存,SWR会直接返回缓存数据;若无缓存则自动发起请求 }, []); return ( <div className={classes.CategoryList}> <h5>Parc de véhicules</h5> <div className={classes.CategoriesCards}> {category.data ? category.data.map((element, index) => ( <CategoryItem category={element.data.name} carNumber={element.stats.nb_vehicles} locating={element.stats.nb_booked} available={element.stats.nb_available} blocked={element.stats.nb_unavailable} percentage={(element.stats.nb_booked / element.stats.nb_vehicles * 100).toFixed(2)} key={index} /> )) : null} </div> </div> ); }; export default CategoryList;
关键改动说明
稳定的请求Key:
用company_id判断生成有效URL,避免了之前mounted状态导致Key频繁切换为null的问题,确保SWR能准确匹配缓存,导航回组件时直接复用缓存数据。正确配置SWR的自动行为:
把所有自动重验证相关的配置项设为false,并将refreshInterval设为0,彻底阻止SWR定时发起请求或在页面聚焦/重连时自动刷新。简化状态管理:
移除了不必要的mounted和parameters状态,改用SWR的onSuccess/onError钩子统一管理loading状态,逻辑更清晰。主动刷新的扩展方案:
如果之后需要主动刷新数据(比如用户手动触发),可以引入useSWRConfig的mutate函数:import { useSWRConfig } from 'swr'; // 在组件内添加 const { mutate } = useSWRConfig(); // 需要刷新时调用 const handleRefresh = () => { mutate(swrKey); // 主动发起请求并更新缓存 };
内容的提问来源于stack exchange,提问作者Peyo33




