useSWR发起无限重复请求问题求助(POST API场景)
解决useSWR配合POST API无限重复调用的问题
问题根源
useSWR 通过缓存key的唯一性判断是否需要发起新请求。你的代码里每次组件渲染时:
formData是新建的FormData实例dataToRequest是新建的对象
这两个都是引用类型,每次渲染都会生成新的内存引用,导致useSWR认为缓存key发生了变化,从而不断重复发起请求。
修复方案
方案1:缓存请求参数+用基础类型生成缓存key(推荐)
用 useMemo 缓存请求参数,只有当核心依赖(id/token)变化时才重新创建;同时用基础类型组合成缓存key,避免引用类型导致的误判:
import { useMemo, useEffect } from 'react'; import useSWR from 'swr'; import { useCookies } from 'react-cookie'; const EventDetail = ({ params }: { params: { id: string } }) => { const id: string = params.id; const [cookies] = useCookies(["token"]); const token = cookies.token; // 缓存请求参数,仅在id或token变化时重新生成 const dataToRequest = useMemo(() => { const formData = new FormData(); formData.append("id", id); return { token, formData }; }, [id, token]); // 用基础类型组合成唯一缓存key const swrKey = useMemo(() => { return [SERVICESADDR.EVENT, id, token]; }, [SERVICESADDR.EVENT, id, token]); const { data, error, isLoading } = useSWR(swrKey, () => fetcher([SERVICESADDR.EVENT, dataToRequest])); if (error) { console.error(error); } // 避免顶层console.log触发不必要的渲染日志干扰 useEffect(() => { if (data) console.log(data); }, [data]); return <div>{id}</div>; }; export default EventDetail;
方案2:自定义key比较函数(备选)
如果坚持用对象作为缓存key,可以通过 isEqual 选项传入深层比较函数,让useSWR正确识别key是否相同:
import { isEqual } from 'lodash'; // ... const { data, error, isLoading } = useSWR( [SERVICESADDR.EVENT, dataToRequest], fetcher, { isEqual: isEqual } );
注意:此方案需要额外引入深层比较工具(如lodash.isEqual),且每次渲染仍会创建新的dataToRequest对象,性能略逊于方案1。
额外优化
如果API返回的是JSON格式,建议把fetcher里的res.text()改为res.json(),方便后续直接处理结构化数据:
export const fetcher = ([url, data]: [ url: string, data: { token: string; formData?: FormData }, ]) => fetch(url, { method: "POST", body: data.formData, headers: { Authorization: `Bearer ${data.token}`, "Accept-Language": "pt", Accept: "application/json", // 匹配返回格式 }, }) .then((res) => { if (!res.ok) throw new Error('请求失败'); return res.json(); });
内容的提问来源于stack exchange,提问作者Carlos Almeida
相关产品推荐
相关产品推荐

