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

Next.js 13:客户端组件导入异步服务端组件报错原因解析

为什么异步Server Component作为Client Component子元素会报错?

我在测试Next.js 13的app目录和React 18的Server Components功能。按照文档指引,我给Server Component添加了async fetch()调用并将组件标记为async,但把它作为Client Component的子元素时,出现了以下错误:

Objects are not valid as a React child (found: [object Promise])
如果把它作为另一个Server Component的子元素则能正常运行,请问这是为什么?

代码示例

page.tsx

import { ClientComp } from './ClientComp'

export default function Page() {
  return <ClientComp />
}

ClientComp.tsx

"use client";
import { ServerComp } from "./ServerComp";

export function ClientComp() {
  {/* @ts-expect-error Async Server Component */}
  return <ServerComp />
}

ServerComp.tsx

export async function ServerComp() {
  return <h2>ServerComp</h2>
}

原因解析

这是因为Client Component无法直接渲染异步的Server Component:

  • Server Component运行在服务端,异步组件返回的Promise会被服务端处理,等待其解析为实际React元素后再发送给客户端,所以作为其他Server Component的子元素时能正常工作。
  • Client Component运行在浏览器端,当你在Client Component中直接调用<ServerComp />,React会把这个异步组件的返回值(Promise)当作普通React子元素处理,但React不允许将Promise作为子元素渲染,因此抛出错误。

解决方法

方法1:将Server Component的渲染结果通过props传递给Client Component

把异步Server Component的渲染逻辑提升到父级Server Component中,等待解析完成后再将结果传给Client Component:
修改page.tsx:

import { ClientComp } from './ClientComp'
import { ServerComp } from './ServerComp'

export default async function Page() {
  const serverContent = await ServerComp()
  return <ClientComp serverContent={serverContent} />
}

修改ClientComp.tsx:

"use client";

export function ClientComp({ serverContent }: { serverContent: React.ReactNode }) {
  return serverContent
}

方法2:用Suspense包裹Server Component(需在Server上下文引入)

如果需要在Client Component内部动态渲染Server Component,可以在父级Server Component中用Suspense包裹后传给Client,或者通过动态导入标记为server组件:

// 在Server Component中处理
import { Suspense } from 'react'
import { ClientComp } from './ClientComp'
import { ServerComp } from './ServerComp'

export default function Page() {
  return (
    <ClientComp>
      <Suspense fallback={<div>加载中...</div>}>
        <ServerComp />
      </Suspense>
    </ClientComp>
  )
}

此时Client Component只需接收子元素并渲染:

"use client";

export function ClientComp({ children }: { children: React.ReactNode }) {
  return <div>{children}</div>
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 09:36:16