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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 13:39:54