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

Next.js 13/14客户端组件用use钩子获取服务端数据失败问题

问题分析与解决

为什么use钩子会报错?

你误解了React use钩子的适用场景:

  • use钩子的设计目的是解析已在服务端生成的Promise,比如从服务端组件传递给客户端组件的异步数据Promise,或是配合Suspense处理组件懒加载这类场景。
  • 当你在客户端组件里直接调用getBottomMenuData()并传入use钩子时,这个调用会在客户端执行——尽管getBottomMenuData标记了'use server',但在客户端组件的渲染流程中直接调用它,会触发React的校验机制:客户端组件的渲染阶段不允许执行异步逻辑,因此抛出了async/await is not yet supported in Client Components的错误。

而useEffect + useState能正常工作的原因是:

  • useEffect的回调是在组件挂载后的客户端副作用阶段执行的,不属于组件渲染流程,因此可以安全调用异步函数并更新状态。

正确的解决方案

如果想在客户端组件中使用use钩子配合服务端数据,需要通过服务端组件作为中间层传递Promise:

  1. 创建服务端组件,在其中调用服务端函数并传递Promise给客户端组件:
// 无'use client'标记,属于服务端组件
import { BottomMenu } from "./BottomMenuClient";
import { getBottomMenuData } from "./BottomMenuData";

export async function BottomMenuWrapper() {
  const dataPromise = getBottomMenuData();
  return <BottomMenu dataPromise={dataPromise} />;
}
  1. 修改客户端组件,接收Promise并使用use钩子解析:
"use client"
import styles from "./BottomMenu.module.css"
import { ActiveType } from "./BottomMenuData";
import { use } from "react";

type BottomMenuProps = {
  dataPromise: Promise<ActiveType>;
};

export function BottomMenu({ dataPromise }: BottomMenuProps) {
  const active = use(dataPromise);
  return <div>当前激活项:{active}</div>;
}

这样getBottomMenuData的调用在服务端完成,传递给客户端的只是一个Promise,use钩子在客户端组件中解析这个Promise就不会触发报错。

总结

  • 客户端组件的渲染阶段不能直接执行异步逻辑,use钩子不能用来直接调用服务端action,只能解析已在服务端生成的Promise。
  • useEffect + useState是客户端组件中直接调用服务端action的常规方式,use钩子则需要配合服务端组件传递Promise的模式使用。

内容的提问来源于stack exchange,提问作者marius

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 02:52:39