Next.js 13客户端组件用SWR重载不刷新数据,如何解决?
问题:Next.js 13 客户端组件部署后重载不重新获取数据?
我正在使用Next.js 13开发天气应用,通过'use client'指令和SWR渲染页面。部署到Vercel后,页面重载时不会重新获取数据,反而表现得像SSR组件一样仅构建一次。难道'use client'不该起作用吗?我遗漏了什么配置才能让页面每次重载都获取数据?
/weather/page.tsx 页面代码
'use client'; import useSWR, { SWRConfig } from 'swr'; import { WeatherUI } from '../sections'; import { CurrentWeatherProps, ForecastProps, LocationProps, } from '../models/Fragments'; import { Loading, Navigation } from '../components'; const fetcher = async (url: string) => { const response = await fetch(url); const data = await response.json(); return data; }; const WeatherData = () => { const { data: rawWeatherData, error } = useSWR( '/api/prismaWeather', fetcher, { refreshInterval: 300000 } ); if (error) { return <div>Error fetching data</div>; } if (!rawWeatherData) { return <Loading />; } const weatherDataLocation = rawWeatherData.data[0] .location as unknown as LocationProps; const weatherDataCurrent = rawWeatherData.data[0] .current as unknown as CurrentWeatherProps; const weatherDataForecast = rawWeatherData.data[0] .forecast as unknown as ForecastProps; const weatherData = { location: weatherDataLocation, current: weatherDataCurrent, forecast: weatherDataForecast, }; return ( <> <Navigation theme={'black'} location={'/weather'} /> <main> <WeatherUI weatherData={weatherData} /> </main> </> ); }; export default WeatherData;
补充:API 代码(/api/prismaWeather/route.ts)
import prisma from '../../lib/prisma'; export async function GET(req, res) { try { const rawWeatherData = await prisma.weatherCurrent.findMany({ orderBy: { createdAt: 'desc', }, take: 1, }); return Response.json({ data: rawWeatherData }); } catch (error) { return Response.json({ error: `Error fetching weather data ${error}` }); } }
原因及解决方案
核心原因
Vercel 对静态资源和API响应有默认缓存策略,即使页面标记了'use client',如果API接口没有明确禁止缓存,Vercel可能会缓存API返回结果;同时SWR默认会复用本地缓存,导致页面重载时不触发新请求。
具体解决方法
- 给API接口添加缓存控制头
修改API的GET方法,强制禁止缓存,确保每次请求都拉取最新数据:
export async function GET(req) { try { const rawWeatherData = await prisma.weatherCurrent.findMany({ orderBy: { createdAt: 'desc', }, take: 1, }); return new Response(JSON.stringify({ data: rawWeatherData }), { headers: { 'Cache-Control': 'no-store, no-cache, must-revalidate, proxy-revalidate', 'Pragma': 'no-cache', 'Expires': '0', }, }); } catch (error) { return new Response(JSON.stringify({ error: `Error fetching weather data ${error}` }), { status: 500, headers: { 'Cache-Control': 'no-store, no-cache, must-revalidate, proxy-revalidate', }, }); } }
- 配置SWR强制重新验证
在SWR的选项中添加revalidateOnMount: true,确保组件挂载时忽略本地缓存,重新请求数据:
const { data: rawWeatherData, error } = useSWR( '/api/prismaWeather', fetcher, { refreshInterval: 300000, revalidateOnMount: true, revalidateOnFocus: true, // 可选:页面重新聚焦时重新验证 revalidateOnReconnect: true // 可选:网络重连时重新验证 } );
- 强制页面为动态渲染(可选)
如果页面需要完全动态,可在page.tsx顶部添加配置,告诉Next.js不要预渲染该页面:
'use client'; export const dynamic = 'force-dynamic'; // 添加这一行 // 剩余代码...
内容的提问来源于stack exchange,提问作者Matoko93
相关产品推荐
相关产品推荐

