停止流式纯文本:使用 React Server Components 解锁交互式 UI

发布: (2026年2月4日 GMT+8 04:00)
8 min read
原文: Dev.to

I’m happy to help translate the article, but I need the actual text you’d like translated. Could you please paste the content of the article (excluding the source link you’ve already provided) here? Once I have the text, I’ll translate it into Simplified Chinese while preserving the original formatting, markdown, and technical terms.

演进:从新闻滚动条到实时广播

旧方式(仅文本)

想象一个实时新闻滚动条。信息不断流动,但它是静态的。客户端是被动的接受者。
如果用户请求,“给我展示 Q3 销售额的图表”,AI 会流回描述图表的文本,或许是一个 JSON 对象。用户必须等流结束后 UI 才能渲染。

新方式(流式 UI)

现在,想象一个实时广播,记者可以动态地在信息流中插入交互式仪表盘、图表和表单。这就是 streamable‑ui 模式。
与其发送 {"chart":"data…"},服务器发送的是序列化的 React 组件:

// Example placeholder – the actual component is streamed from the server

客户端接收后立即进行 hydrate,用户可以在 AI 仍在生成其余响应时进行悬停、缩放和点击。

架构:RSC 与服务器操作

它是如何在底层工作的?它依赖于两个支柱:

  1. React Server Components (RSCs) – 服务器渲染组件树并将其序列化为特殊负载(使用 React 的 Flight 协议)。该负载通过 SSE(服务器发送事件)进行流式传输。
  2. Server Actions – 流式传输的组件不仅仅是静态 HTML。它们可以包含交互元素(按钮、表单),这些元素会通过 Server Actions 触发服务器上的安全函数。

这形成了一个双向流:

方向描述
Server → Client流式传输 UI 组件。
Client → Server用户点击该组件内的按钮。
Server → ClientServer Action 执行,可能触发更多 AI 生成并流式传输组件。

“实时购物车”类比

想象一下直播主在卖产品。

模式体验
仅文字主播描述商品。你在聊天中输入提问。
流媒体 UI主播在视频画面上直接叠加一个 “加入购物车” 按钮和尺码选择器。你可以 立即 点击,而无需暂停视频。

这就是我们正在构建的体验。

代码示例:流式 AI 仪表盘

我们将构建一个 SaaS 功能,让 AI 生成摘要报告并以交互式 React 组件的形式流式传输。

1️⃣ 服务端实现

文件: app/api/generate-report/route.ts

// app/api/generate-report/route.ts
import { streamUI } from 'ai/rsc';
import { OpenAI } from 'openai';

const openai = new OpenAI({
  apiKey: process.env.OPENAI_API_KEY || '',
});

// The component to be streamed
const ReportComponent = ({ data }: { data: string }) => {
  return (
    <div>
      <h3>AI Generated Report</h3>
      <p>{data}</p>
      <button
        onClick={() => alert('Report acknowledged!')}
        className="mt-3 px-3 py-1 text-xs bg-blue-600 text-white rounded hover:bg-blue-700"
      >
        Acknowledge
      </button>
    </div>
  );
};

export async function POST(req: Request) {
  const { prompt } = await req.json();

  const result = await streamUI({
    model: 'gpt-4-turbo-preview',
    system: 'You are a helpful assistant that generates concise reports.',
    prompt: `Generate a summary report for: ${prompt}`,

    // The Magic Mapping:
    // When the AI generates text, we wrap it in our React Component
    text: ({ content }) => {
      return <ReportComponent data={content} />;
    },

    initial: 'Generating report...',
  });

  return result.toAIStreamResponse();
}

2️⃣ 客户端实现

文件: app/page.tsx

// app/page.tsx
'use client';

import { useCompletion } from 'ai/react';

export default function DashboardPage() {
  const {
    completion,
    input,
    handleInputChange,
    handleSubmit,
    isLoading,
  } = useCompletion({
    api: '/api/generate-report',
  });

  return (
    <div>
      <h2>SaaS Dashboard</h2>

      <form onSubmit={handleSubmit}>
        <input
          value={input}
          onChange={handleInputChange}
          placeholder="Enter prompt"
        />
        <button type="submit" disabled={isLoading}>
          Generate
        </button>
      </form>

      <h3>Output:</h3>
      {/* The SDK handles the deserialization of the RSC payload */}
      {completion ? (
        // The payload is already a React element, so we can render it directly.
        <>{completion}</>
      ) : (
        <p>No report generated yet.</p>
      )}
    </div>
  );
}

注意: useCompletion 返回的 completion 是一个 React 元素(或元素树),SDK 会从流式 RSC 负载中重建它。无需使用 dangerouslySetInnerHTML

回顾

  • Streaming UI 让服务器在 AI 仍在生成 时向客户端推送交互式 React 组件。
  • React Server Components + Server Actions 为我们提供安全、双向、实时的 UI 管道。
  • 该模式可与 Vercel AI SDK(服务器端 streamUI,客户端 useCompletion)配合使用,并可适配任何基于 LLM 的工作流。

现在你可以超越静态文本,构建真正 实时 的 AI 增强体验! 🚀

{isLoading && (
  <div>
    ● Streaming component...
  </div>
)}

全屏控制

Enter fullscreen mode
Exit fullscreen mode

Source:

高级模式:LangGraph 与最大迭代策略

当你将流式 UI 与 AI 代理结合时,会进入一个循环工作流:

  1. AI 生成 UI。
  2. 用户与之交互。
  3. 该交互反馈给 AI,以生成 下一步

这非常强大,但也很危险。没有防护措施,AI 可能会陷入无限生成组件的循环。

解决方案:最大迭代策略

使用 LangGraph,我们可以将 AI 逻辑结构化为有状态的图。
添加一个条件边(即“策略”),检查迭代计数。如果计数超过限制(例如 5 步),图会强制转向 END 节点,优雅地终止流程。

这可确保即使 AI 逻辑出现混乱,你的应用仍保持稳定。

常见陷阱需避免

  • 幻觉 JSON – 不要让 LLM 生成 React 组件结构(JSON/JSX),它会失败。相反,让它生成 内容,并在服务器上将该内容映射到预定义的组件(如代码示例所示)。
  • Vercel 超时 – 无服务器函数有超时限制(10 秒–15 秒)。如果你的 AI 生成较慢,流可能会被截断。始终使用 streamUI(它能高效保持连接活跃)并优化提示词。
  • 水合错误 – 服务器组件无法访问浏览器 API(windowdocument)。如果需要客户端交互(如示例中的 onClick),确保事件处理逻辑由客户端水合过程处理,或包装在客户端组件中。

结论

流式传输 React 组件让我们从 “Generative Text” 进入 “Generative UI”。

它将用户体验从被动的阅读‑等待循环转变为主动的、迭代的协作。通过利用 Vercel AI SDK 和 React Server Components,你可以构建感觉瞬时且深度交互的应用。AI 不仅告诉你该怎么做;它在你眼前为你构建完成任务的工具。

这里展示的概念和代码直接取自书籍 The Modern Stack: Building Generative UI with Next.js, Vercel AI SDK, and React Server Components ——Amazon Link —— 属于 AI with JavaScript & TypeScript SeriesAmazon Link)。

另外,请查看 Leanpub 上的所有其他编程电子书。

Back to Blog

相关文章

阅读更多 »

ReactJS ~React Server Components~

ReactJS 的封面图片 ~React Server Components~ https://media2.dev.to/dynamic/image/width=1000,height=420,fit=cover,gravity=auto,format=auto/https%3A%2F%2Fdev...