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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 15:47:41