Next.js 14服务器组件能否用useCallback/useMemo?遇await错误如何解决?
问题解答:Next.js 14 服务器组件中使用useCallback/useMemo报错
核心结论
React的useCallback、useMemo等钩子完全不支持在服务器组件中使用,这是React和Next.js App Router的核心设计规范,不是可规避的“问题”,而是用法错误。
报错原因
- 服务器组件运行在服务器端,没有React客户端运行时环境,钩子依赖客户端的组件状态管理、渲染生命周期等机制,服务器端根本不存在这些上下文。
- 你代码中的
async组件在App Router里默认就是服务器组件,加上await语句后,组件的渲染流程进入异步阶段,React的钩子上下文会直接销毁,所以会抛出Cannot read properties of null (reading 'useCallback')这类错误。
解决方案
要满足公司组件一致性要求,同时符合Next.js架构规范,正确的做法是拆分组件边界:
1. 拆分服务器组件与客户端组件
- 服务器组件:负责异步数据获取、静态内容渲染,不使用任何React钩子。
- 客户端组件:添加
'use client'指令声明,专门处理交互逻辑、使用钩子,接收服务器组件传递的props数据。
2. 修改后的代码示例
服务器组件(Test.tsx)
// 无需添加'use client',默认是服务器组件 export const Test = async () => { const getAsyncStuff = async () => 'async stuff'; const asyncData = await getAsyncStuff(); // 将异步数据传递给客户端组件 return <TestClient asyncData={asyncData} />; };
客户端组件(TestClient.tsx)
'use client'; // 必须添加此指令,声明为客户端组件 import { useCallback, useMemo } from 'react'; type TestClientProps = { asyncData: string; }; export const TestClient = ({ asyncData }: TestClientProps) => { // 这里可以正常使用useCallback const getStuff = useCallback(() => 'stuff', []); // 正常使用useMemo const stuff = useMemo(() => 'stuff', []); return ( <div> <p>异步数据:{asyncData}</p> <p>{getStuff()}</p> <p>{stuff}</p> </div> ); };
3. 组件一致性的保障方案
如果公司要求组件写法统一,可以制定规范:
- 所有需要使用钩子的逻辑,统一放在带
'use client'的客户端组件中。 - 服务器组件专注于数据层和静态渲染,通过props将数据传递给客户端组件,保持数据层与交互层的分离,同时保证组件写法的一致性。
内容的提问来源于stack exchange,提问作者Gyan
相关产品推荐
相关产品推荐

