Next.js Request Memoization缓存失效,请求重复执行如何修复?
修复Next.js异步组件重复请求的问题
在Next.js项目中,ClientLayout包含Header和Footer两个异步组件,二者都调用fetchDepartments获取部门数据,但请求缓存未生效,API端确认收到两次重复请求,以下是两种可行的修复方案:
方案一:将数据请求提升至父组件(推荐)
把数据获取逻辑移到共同的父组件ClientLayout中,仅请求一次后将数据传递给子组件,符合React自上而下的数据流原则:
修改ClientLayout:
export default async function ClientLayout({ children, }: Readonly<{ children: React.ReactNode; }>) { // 仅在父组件调用一次,复用缓存数据 const departments = await fetchDepartments(); return ( <> <Header departments={departments} /> <main>{children}</main> <Footer departments={departments} /> </> ); }
修改Header组件,接收父组件传递的数据:
// 替换any为实际的数据类型,提升类型安全性 export default async function Header({ departments }: { departments: any }) { // 移除内部的fetchDepartments调用 return ( <header className={styles.navbar}> <nav className={`${styles.container} container`}> <Link href="/" className={styles.logo}> <Image src={logo} priority={true} alt="logo" /> </Link> <DepartmentsSelectContainer /> <Links /> <div className={styles.bookingBtn}> <Link className={`btn yellow sm`} href="/contacts"> Запис на прийом </Link> </div> </nav> </header> ); }
修改Footer组件,接收父组件传递的数据:
// 替换any为实际的数据类型,提升类型安全性 export default async function Footer({ departments }: { departments: any }) { // 移除内部的fetchDepartments调用 return <div>currently empty</div>; }
方案二:用React.cache包装数据请求函数
如果不想调整组件结构,可以使用React.cache缓存fetchDepartments的返回值,确保多次调用返回同一个Promise:
修改fetchDepartments函数:
import { cache } from 'react'; // 改为命名导出,确保所有组件导入的是同一缓存实例 export const fetchDepartments = cache(async () => { const first = Date.now(); const data = await fetch(`${basicUrl}/departments`); const second = Date.now(); console.log(second - first); const parsedData = await data.json(); console.log("parsedData", parsedData); return parsedData; });
同时更新Header和Footer中的导入方式:
import { fetchDepartments } from './path/to/fetchDepartments';
原问题原因
Next.js的自动请求缓存(Request Memoization)仅在同一个Server Component的渲染上下文中生效——即同一组件树内的相同fetch请求会被复用。但Header和Footer是独立的异步Server Component,它们的fetch调用处于不同的渲染上下文,因此默认不会复用缓存。上述两种方案分别通过数据提升共享结果、缓存函数返回值解决了重复请求问题。
内容的提问来源于stack exchange,提问作者Dmytro
相关产品推荐
相关产品推荐

