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

Next.js 13 App Router中Server Actions与路由缓存问题咨询

问题原因与解决方案

核心原因

你的问题出在Next.js App Router的客户端路由缓存机制上:

  • 使用Link组件的客户端导航会优先读取Next.js的Router Cache中缓存的页面内容,而revalidatePath("/")仅在服务端触发页面的重新生成,不会主动通知客户端更新本地缓存。
  • 手动刷新页面会绕过客户端缓存,直接从服务端拉取最新生成的页面资源,因此能看到新创建的Todo。
  • 修改prefetch属性仅控制预加载的时机,无法解决客户端缓存未同步服务端更新的核心问题。

可行解决方案

1. 客户端提交后强制刷新缓存

在createTodo执行完成后,除了调用服务端的revalidatePath,还要在客户端用useRouter的refresh()方法强制刷新缓存,再跳转回首页:

'use client';
import { useRouter } from 'next/navigation';
import createTodo from '@/actions/todos';

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

  async function handleSubmit(formData) {
    await createTodo(formData);
    router.refresh(); // 强制客户端重新拉取服务端最新资源
    router.push('/');
  }

  return (
    <form action={handleSubmit}>
      {/* 你的表单输入项 */}
      <button type="submit">添加Todo</button>
    </form>
  );
}

router.refresh()会保留客户端路由的体验(无全页刷新),但会让客户端重新请求服务端的最新页面数据,同步服务端的更新。

2. 禁止首页数据缓存

如果希望首页每次客户端导航都获取最新数据,可以在首页组件中使用unstable_noStore(Next.js 13.4+)禁止数据缓存:

import { unstable_noStore as noStore } from 'next/cache';
import getTodos from '@/actions/todos';

export default async function HomePage() {
  noStore(); // 标记此页面数据不被缓存
  const todos = await getTodos();

  return (
    <ul>
      {todos.map(todo => (
        <li key={todo.id}>{todo.title}</li>
      ))}
    </ul>
  );
}

这种方式会让每次客户端导航到首页时,都重新执行getTodos获取最新数据,但会增加服务端的请求次数,适合数据更新频繁的场景。

3. 用标签化缓存精准更新

如果你的getTodos函数使用了缓存标签,可以用revalidateTag替代revalidatePath,实现更精准的缓存更新:

// actions/todos.js
import { revalidateTag } from 'next/cache';

export async function getTodos() {
  const res = await fetch(`${process.env.DATABASE_URL}/todos`, {
    next: { 
      tags: ['todos'], // 给缓存资源打标签
      revalidate: 86400 // 默认缓存时长
    }
  });
  return res.json();
}

export async function createTodo(formData) {
  await fetch(`${process.env.DATABASE_URL}/todos`, {
    method: 'POST',
    body: formData
  });
  revalidateTag('todos'); // 仅重新验证带有'todos'标签的缓存资源
}

搭配客户端的router.refresh()使用,既能精准更新服务端缓存,又能同步客户端的缓存内容。

内容的提问来源于stack exchange,提问作者Ognjen Mišić

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 04:43:22