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
相关产品推荐
相关产品推荐

