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

Next.js 14服务器组件点击按钮重新获取数据问题求助

解决Next.js 14服务器组件数据缓存与手动刷新问题

1. 先解决页面刷新时数据不更新的缓存问题

Next.js默认会缓存服务器组件的渲染结果和数据请求,可通过以下两种方式禁用缓存:

方式一:在服务器组件中全局禁用缓存

导入unstable_noStore并调用,强制每次请求都重新获取数据:

import getSummoner from "@/js/getSummoner";
import { unstable_noStore } from 'next/cache';

const Summoner = async ({ params }) => {
  unstable_noStore(); // 禁用缓存,确保每次请求都重新拉取数据
  const search = params.search;

  let summoner = await getSummoner(search);

  if (summoner) {
    return (
      <div className="flex flex-col items-center gap-2 mb-2">
        <UpdateButton />
        {/* 其他使用summoner数据的子组件 */}
      </div>
    );
  }
};

export default Summoner;

方式二:在数据请求中单独设置缓存策略

如果getSummoner内部用fetch调用API,直接在请求中配置缓存规则:

// getSummoner.js
export default async function getSummoner(search) {
  const res = await fetch(`YOUR_API_ENDPOINT?search=${search}`, {
    cache: 'no-store', // 禁用该请求的缓存
    // 也可使用 revalidate: 0 实现相同效果
    // next: { revalidate: 0 }
  });
  return res.json();
}

2. 添加手动刷新按钮(客户端组件触发服务器组件重渲染)

创建一个客户端组件UpdateButton,利用useRouter的refresh()方法触发路由刷新,迫使服务器组件重新执行并获取最新数据:

// components/UpdateButton.js
'use client';

import { useRouter } from 'next/navigation';

export default function UpdateButton() {
  const router = useRouter();

  const handleRefresh = () => {
    router.refresh(); // 触发路由刷新,服务器组件会重新渲染并拉取最新数据
  };

  return (
    <button onClick={handleRefresh} className="px-4 py-2 bg-blue-500 text-white rounded">
      刷新数据
    </button>
  );
}

3. 进阶:用revalidateTag实现精准刷新(可选)

如果不想触发全页面刷新,可给数据请求添加标签,通过API路由触发精准缓存失效:

步骤1:给数据请求添加专属标签

// getSummoner.js
export default async function getSummoner(search) {
  const res = await fetch(`YOUR_API_ENDPOINT?search=${search}`, {
    next: { tags: [`summoner-${search}`] } // 为该请求添加唯一标签
  });
  return res.json();
}

步骤2:创建用于触发缓存失效的API路由

// app/api/revalidate/route.js
import { revalidateTag } from 'next/cache';
import { NextResponse } from 'next/server';

export async function POST(request) {
  const { tag } = await request.json();
  revalidateTag(tag); // 使对应标签的缓存失效
  return NextResponse.json({ revalidated: true, now: Date.now() });
}

步骤3:修改UpdateButton调用API实现精准刷新

// components/UpdateButton.js
'use client';

import { usePathname } from 'next/navigation';

export default function UpdateButton() {
  const pathname = usePathname();
  const search = pathname.split('/').pop(); // 从当前路径提取search参数,需根据实际路由调整

  const handleRefresh = async () => {
    await fetch('/api/revalidate', {
      method: 'POST',
      body: JSON.stringify({ tag: `summoner-${search}` })
    });
    router.refresh(); // 刷新页面加载最新数据
  };

  return (
    <button onClick={handleRefresh} className="px-4 py-2 bg-blue-500 text-white rounded">
      刷新数据
    </button>
  );
}

以上方案既保留了服务器组件的性能优势,又满足了API只能从后端发起的要求,同时实现了手动刷新数据的功能。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 13:35:14