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

Next.js 14中Router.refresh()失效问题求助

问题描述

我的应用结构如下:

.
└── /course/  
    ├── page.tsx
    └── create-section-button.tsx
  • page.tsx 是服务端组件,通过Prisma获取数据展示课程章节列表,并引入客户端组件 create-section-button.tsx
  • 客户端组件的点击事件处理逻辑:
"use client"

import { createCourseSection } from "@/actions";
import { useRouter } from "next/navigation";

async function handleClick() {
      setLoading(true);
      await createCourseSection({
        courseSlug,
        sectionName: `Section ${secNum}`,
        index: secNum,
      });
      setLoading(false);
      router.refresh();
    }
  • createCourseSection 是仅执行 prisma.section.create({}) 的服务端动作
  • 该功能在Next.js 13中运行正常,但升级到Next.js 14并使用 unstable_noStore() 后,router.refresh() 不再生效
解决方案

1. 确保 unstable_noStore() 正确配置

在服务端组件 page.tsx 的数据获取逻辑前添加 unstable_noStore(),确保组件完全动态,避免缓存干扰:

// course/page.tsx
import { unstable_noStore as noStore } from 'next/cache';
import { prisma } from '@/lib/prisma';
import CreateSectionButton from './create-section-button';

export default async function CoursePage({ params }: { params: { slug: string } }) {
  noStore(); // 必须放在数据查询之前
  const sections = await prisma.section.findMany({
    where: { courseSlug: params.slug },
    orderBy: { index: 'asc' }
  });

  return (
    <div>
      <h1>课程章节</h1>
      <ul>
        {sections.map(section => (
          <li key={section.id}>{section.name}</li>
        ))}
      </ul>
      <CreateSectionButton secNum={sections.length + 1} courseSlug={params.slug} />
    </div>
  );
}

2. 改用服务端 revalidatePath 替代客户端刷新

在服务端动作中直接调用 revalidatePath,触发目标页面的重新验证,这是Next.js 14 App Router中更可靠的数据更新方式:

// @/actions/index.ts
import { prisma } from '@/lib/prisma';
import { revalidatePath } from 'next/cache';

export async function createCourseSection(data: { courseSlug: string; sectionName: string; index: number }) {
  await prisma.section.create({
    data: {
      courseSlug: data.courseSlug,
      name: data.sectionName,
      index: data.index
    }
  });
  // 重新验证对应课程页面的路径,确保数据实时更新
  revalidatePath(`/course/${data.courseSlug}`);
}

修改客户端组件的 handleClick,移除 router.refresh():

async function handleClick() {
  setLoading(true);
  await createCourseSection({
    courseSlug,
    sectionName: `Section ${secNum}`,
    index: secNum,
  });
  setLoading(false);
}

3. 验证 useRouter 导入正确性

确保客户端组件使用的是App Router的 useRouter,而非Pages Router的旧版:

// 正确导入方式
import { useRouter } from "next/navigation";

4. 客户端强制重新渲染(备选方案)

如果上述方法仍不生效,可以通过状态触发组件重新渲染:

"use client"
import { createCourseSection } from "@/actions";
import { useState } from "react";

export default function CreateSectionButton({ courseSlug, secNum }) {
  const [loading, setLoading] = useState(false);
  const [refreshKey, setRefreshKey] = useState(0);

  async function handleClick() {
    setLoading(true);
    await createCourseSection({
      courseSlug,
      sectionName: `Section ${secNum}`,
      index: secNum,
    });
    setLoading(false);
    setRefreshKey(prev => prev + 1); // 更新状态触发重新渲染
  }

  return (
    <button onClick={handleClick} disabled={loading} key={refreshKey}>
      添加新章节
    </button>
  );
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 11:01:32