React 19 Beta中如何正确标记服务端组件以消除警告
我写了两个文件测试React 19 Beta的服务端组件,代码如下:
App.jsx
'use client'; import React, { Suspense, useState } from 'react'; import TestServer from './TestServer'; import clsx from 'clsx'; export default function App() { const [red, setRed] = useState(false); return ( <div className={clsx("p-3 m-3", red && "border border-2 border-danger")}> <Suspense fallback={<p>Loading...</p>}> <header> <h1>React 19 Test</h1> <TestServer timeout={2000} /> <button onClick={() => setRed(!red)}>Toggle Red Border</button> </header> </Suspense> </div> ); }
TestServer.jsx
'use server'; export default async function TestServer({timeout = 1000}) { const response = await new Promise((resolve) => { setTimeout(() => { resolve('Server is running'); }, timeout); }); return <p>{response}</p>; }
运行功能符合预期:组件会挂起2秒显示加载文本,之后展示响应内容和按钮;点击按钮会重新触发流程并更新样式。但控制台出现两条警告:
async/await is not yet supported in Client Components, only Server Components. This error is often caused by accidentally adding
'use client'to a module that was originally written for the server.
A component was suspended by an uncached promise. Creating promises inside a Client Component or hook is not yet supported, except via a Suspense-compatible library or framework.
我推测服务端组件仍在客户端运行,手动创建Promise并将TestServer设为异步的操作触发了警告。请问如何正确实现该测试以消除这些警告?
问题根源
这两条警告的核心原因是:React 19的服务端组件不允许直接在组件内部编写未缓存的异步Promise逻辑。虽然你给TestServer加上了'use server'指令,但当前写法没有遵循服务端组件的异步数据规范——直接在组件内await裸Promise,会导致逻辑意外跑到客户端执行,触发警告。
修正步骤
核心是把异步逻辑抽离出来,用React提供的缓存函数包裹,确保逻辑仅在服务端执行,且结果被缓存。
修改后的TestServer.jsx
'use server'; import { unstable_cache } from 'react'; // 用unstable_cache包裹异步逻辑,指定缓存标识和刷新规则 const getServerStatus = unstable_cache( async (timeout) => { return new Promise(resolve => { setTimeout(() => resolve('Server is running'), timeout); }); }, ['server-status'], // 唯一缓存键,用于区分不同缓存条目 { revalidate: 0 } // 0表示永不自动刷新,可按需设置为具体秒数 ); export default async function TestServer({ timeout = 1000 }) { const response = await getServerStatus(timeout); return <p>{response}</p>; }
App.jsx无需修改
原代码的写法是正确的:App作为客户端组件负责交互逻辑,用Suspense包裹服务端组件的方式符合React 19的设计规范。
为什么这样能解决警告?
unstable_cache(React 19正式版会改名为cache)会将异步逻辑锁定在服务端执行,同时缓存结果,避免逻辑跑到客户端触发async/await相关警告。- 通过缓存函数处理异步逻辑,符合React 19对服务端组件异步数据的处理规则,消除了“未缓存Promise导致组件挂起”的警告。
额外提示
如果使用Next.js 14+适配React 19,也可以利用fetch的自动缓存特性模拟服务端请求,写法更贴近真实场景:
'use server'; import { unstable_cache } from 'react'; const getServerStatus = unstable_cache(async () => { // 模拟服务端API请求,fetch默认会被React自动缓存 const res = await fetch('https://example.com/api/server-status', { cache: 'force-cache' }); return res.text(); }); export default async function TestServer() { const response = await getServerStatus(); return <p>{response}</p>; }
内容的提问来源于stack exchange,提问作者Ptolemy2002

