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

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默认会复用本地缓存,导致页面重载时不触发新请求。

具体解决方法

  1. 给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',
      },
    });
  }
}
  1. 配置SWR强制重新验证
    在SWR的选项中添加revalidateOnMount: true,确保组件挂载时忽略本地缓存,重新请求数据:
const { data: rawWeatherData, error } = useSWR(
  '/api/prismaWeather',
  fetcher,
  { 
    refreshInterval: 300000,
    revalidateOnMount: true,
    revalidateOnFocus: true, // 可选:页面重新聚焦时重新验证
    revalidateOnReconnect: true // 可选:网络重连时重新验证
  }
);
  1. 强制页面为动态渲染(可选)
    如果页面需要完全动态,可在page.tsx顶部添加配置,告诉Next.js不要预渲染该页面:
'use client';
export const dynamic = 'force-dynamic'; // 添加这一行

// 剩余代码...

内容的提问来源于stack exchange,提问作者Matoko93

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 14:47:41