Next.js 13.3 App目录下SWR无法每次请求更新数据问题
问题分析与解决方案
核心原因
- App Router API路由默认静态缓存:Next.js 13 App目录下的
route.ts默认会被静态优化,即使你在fetch中设置了cache: "no-cache",Next.js仍会缓存API响应,导致后续请求复用旧数据。 - SWR默认缓存策略:SWR会将数据缓存到内存和本地存储,页面刷新时优先读取缓存,不会自动触发重新请求。
而Next.js 12的Pages Router中,API路由默认是动态的,不会静态缓存,同时页面刷新时SWR的缓存会被重置,所以能正常更新数据。
解决方案
1. 禁用API路由的静态缓存
在api/hello/route.ts中添加revalidate: 0,强制API路由每次请求都重新获取数据:
import { NextResponse } from 'next/server'; export const revalidate = 0; // 关键:禁用静态缓存 export async function GET(request: Request) { const response = await fetch( "https://timeapi.io/api/Time/current/zone?timeZone=Europe/Kiev", { cache: "no-cache" } ); const data = await response.json(); console.log(data); return NextResponse.json(data); }
2. 配置SWR强制重新验证
在time.tsx中调整SWR的配置,确保每次页面加载/刷新时都重新请求数据:
"use client"; import useSWR from "swr"; import { fetcher } from "~/lib/fetcher"; export const Time = () => { const { data, error, isLoading } = useSWR("api/hello", fetcher, { revalidateOnMount: true, // 组件挂载时强制重新验证 revalidateOnFocus: true, // 页面重新获得焦点时刷新数据 dedupingInterval: 0, // 禁用请求去重,确保每次请求都发新请求 }); if (error) { return <div>error</div>; } if (isLoading) return <div>loading...</div>; console.log(data); return ( <div> <div>{data.dateTime}</div> </div> ); };
3. 可选:验证页面组件的动态渲染
你的page.tsx已经设置了export const revalidate = 0,这确保了页面本身是动态渲染的,虽然客户端组件的SWR请求不受此直接影响,但保持这个配置可以避免页面静态缓存带来的其他问题。
验证效果
修改后,刷新页面时,API路由会重新调用timeapi.io获取最新时间,SWR也会放弃缓存重新请求,最终页面会显示最新的日期时间。
内容的提问来源于stack exchange,提问作者Digweed
相关产品推荐
相关产品推荐

