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

React Server Component在Suspense中渲染后客户端崩溃求助

React Server Component迁移后客户端崩溃问题排查与解决

问题情况

将React组件迁移为React Server Component(RSC),标记为async并使用<Suspense>包裹后,服务端能正常接收请求、渲染组件并返回响应,但客户端出现崩溃,无法正常显示组件,同时抛出状态更新相关警告。

代码示例

page.tsx

<Suspense fallback={<div>Loading...</div>}>
    <TestServerComponent>
        {JSON.stringify(content, undefined, 4)}
    </TestServerComponent>
</Suspense>

TestServerComponent.tsx

'use server'
 
export async function TestServerComponent(props?: PropsWithChildren) {
    console.log('TestServerComponent render:', props)
    return (
        <pre>{props?.children}</pre>
    )
}

服务端与响应信息

  • 服务端日志:
TestServerComponent render: { children: '{\n    "test": true\n}' }
  • HTTP响应内容:
0:["$@1",["development",null]]
1:["$","pre",null,{"children":"{\n    \"test\": true\n}"}]

客户端错误

Warning: Cannot update a component (Router) while rendering a different component (proxy). To locate the bad setState() call inside proxy, follow the stack trace as described in https://reactjs.org/link/setstate-in-render
at proxy
at Suspense
at div
at Page (webpack-internal:///(app-pages-browser)/./app/page.tsx:15:82)

## 问题原因
核心问题在于**服务器组件(RSC)接收了客户端生成的`children`**:
- RSC的渲染逻辑完全在服务端执行,你在客户端通过`JSON.stringify(content...)`生成children并传递给RSC,会导致服务端渲染的静态内容与客户端hydration时的动态计算结果出现一致性冲突。
- React在hydration过程中检测到内容不匹配,触发内部状态调整,进而引发Router组件的状态更新警告(Router会因组件渲染异常尝试修正状态)。

## 解决方案
### 方案1:将数据处理逻辑移至服务器组件内部
如果`content`可以在服务端获取或处理,直接在RSC内部完成序列化操作,避免客户端传递动态children:
```tsx
// TestServerComponent.tsx
'use server'
 
export async function TestServerComponent() {
    // 服务端获取content(示例为本地数据,实际可从数据库/API获取)
    const content = { test: true };
    const contentStr = JSON.stringify(content, undefined, 4);
    
    console.log('TestServerComponent render:', contentStr)
    return (
        <pre>{contentStr}</pre>
    )
}
// page.tsx
<Suspense fallback={<div>Loading...</div>}>
    <TestServerComponent />
</Suspense>

方案2:通过props传递序列化后的内容(而非children)

如果content必须在客户端生成,将序列化后的字符串通过props传递给RSC(确保props是可序列化的JSON类型):

// page.tsx
<Suspense fallback={<div>Loading...</div>}>
    <TestServerComponent contentStr={JSON.stringify(content, undefined, 4)} />
</Suspense>
// TestServerComponent.tsx
'use server'
 
export async function TestServerComponent({ contentStr }: { contentStr: string }) {
    console.log('TestServerComponent render:', contentStr)
    return (
        <pre>{contentStr}</pre>
    )
}

注意:如果content是客户端状态(如useState的返回值),确保传递给RSC的contentStr是可序列化的基础类型,避免传递复杂对象或React节点。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 12:36:07