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

Next.js中useSWR调用toISOString引发无限API请求问题咨询

问题根因

useSWR 会以传入的第一个参数作为请求缓存的唯一key,只要key发生变化,就会自动触发新的请求。你当前的代码在每次组件渲染时,都会重新创建Date实例并调用toISOString(),哪怕两次渲染只间隔几毫秒,生成的ISO字符串末尾的毫秒数也会不同,导致请求key持续变化。新请求返回后又会触发组件重渲染,进而生成新的key,就形成了无限请求的死循环。

解决方案

你只需要把生成的日期字符串缓存起来,避免每次渲染都生成新值即可,最常用的方式是用useMemo包裹日期生成逻辑:

首先修改导入语句,引入useMemo:

import { useRouter } from "next/router";
import { useMemo } from "react"; // 新增导入

然后把原来的日期生成逻辑替换为useMemo包裹的版本,依赖项设为空数组,保证只会在组件首次渲染时计算一次:

const UserData = () => {
  const router = useRouter();
  const { id } = router.query;
  // 用useMemo缓存日期值,仅首次渲染计算一次
  const ssd = useMemo(() => {
    const today = new Date();
    const yesterday = new Date(today);
    yesterday.setDate(yesterday.getDate() - 1);
    return yesterday.toISOString();
  }, []);

  const result = useSWR(`/api/user/${id}/${ssd}`, fetcher, {
    revalidateOnFocus: false
  });
  // 其余逻辑保持不变
}

如果你的业务场景需要在特定条件下更新日期(比如页面停留超过零点时刷新日期),只需要把对应的触发条件加入useMemo的依赖数组即可。如果只需要精确到天的日期,也可以把toISOString()返回的结果切掉时间部分,避免毫秒级差异带来的key变化:

return yesterday.toISOString().slice(0, 10); // 仅返回YYYY-MM-DD格式

如果router.query.id是异步加载的(比如页面首次渲染时还没拿到路由参数),可以给useSWR的key加判断,避免发起无效请求:

const result = useSWR(id ? `/api/user/${id}/${ssd}` : null, fetcher, {
  revalidateOnFocus: false
});

内容的提问来源于stack exchange,提问作者w. Patrick Gale

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 12:00:04