NextJS报错:使用cache时提示Not implemented,求解决方案
解决React cache在客户端组件中报错“Not implemented when using cache”的问题
问题根源
你用React的cache包裹了getUserMenu函数,但这个API仅支持在服务端组件(Server Component)中使用,客户端组件(标记了'use client')调用带cache的函数时,因为客户端环境没有实现该API,就会抛出这个错误。
解决方案1:服务端获取数据后传给客户端组件
把菜单数据的获取逻辑放到服务端组件里,再将数据作为props传给客户端的AdminLayout:
- 创建一个服务端组件
AdminLayoutWrapper.tsx:
// 无'use client'标记,默认是服务端组件 import AdminLayout from './AdminLayout'; import { getUserMenu } from '@/utils/getUserMenu'; export default async function AdminLayoutWrapper({ children }) { // 服务端调用带cache的函数,正常复用请求 const items = await getUserMenu(); return <AdminLayout items={items}>{children}</AdminLayout>; }
- 修改客户端的
AdminLayout.tsx,直接接收props:
'use client'; import type { ReactNode } from 'react'; import Nav from '@/lib/components/Nav'; type IAdminLayoutProps = { children?: ReactNode; items: Array<{ /* 替换成你的菜单数据类型 */ }>; }; export default function AdminLayout({ children, items }: IAdminLayoutProps) { return ( <main> <Nav items={items} /> {children} </main> ); }
之后页面路由里使用AdminLayoutWrapper作为布局即可,这样数据在服务端获取并缓存,客户端只负责渲染。
解决方案2:客户端改用Next.js fetch缓存或SWR/React Query
如果必须在客户端组件里获取菜单数据,去掉React的cache,改用客户端支持的缓存方案:
方式A:用Next.js fetch的缓存选项
修改getUserMenu去掉cache包裹,改用fetch自身的缓存配置:
export const getUserMenu = async () => { const headers = {}; const params = { headers, method: 'GET', next: { revalidate: 60 }, // 保持重新验证逻辑 cache: 'force-cache' // 启用fetch缓存 }; const menusReq = await fetch('/api/Menu', { ...params }); if (menusReq.status === 200) { const json = await menusReq.json(); return json.data ?? []; } return []; };
然后客户端组件可以继续用use钩子:
'use client'; import type { ReactNode } from 'react'; import { use } from 'react'; import Nav from '@/lib/components/Nav'; import { getUserMenu } from '@/utils/getUserMenu'; type IAdminLayoutProps = { children?: ReactNode; }; const dataPromise = getUserMenu(); export default function AdminLayout({ children }: IAdminLayoutProps) { const items = use(dataPromise); return ( <main> <Nav items={items} /> {children} </main> ); }
方式B:用SWR做客户端缓存(推荐)
SWR更适合客户端数据管理,自带缓存、重新验证等功能:
- 先安装SWR:
npm install swr - 修改
AdminLayout.tsx:
'use client'; import type { ReactNode } from 'react'; import useSWR from 'swr'; import Nav from '@/lib/components/Nav'; import { getUserMenu } from '@/utils/getUserMenu'; type IAdminLayoutProps = { children?: ReactNode; }; export default function AdminLayout({ children }: IAdminLayoutProps) { const { data: items = [] } = useSWR('user-menu', getUserMenu, { revalidateInterval: 60000, // 和revalidate时间一致,60秒 revalidateOnFocus: false // 可选,关闭焦点重新验证 }); return ( <main> <Nav items={items} /> {children} </main> ); }
内容的提问来源于stack exchange,提问作者Lokut
相关产品推荐
相关产品推荐

