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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 10:42:44