useChat 对话 UI

useChat 来自 @ai-sdk/react(不是 ai 包)。它负责:向 /api/chat 发 POST、把 UI Message 流拼回 messages、管理 status / error。布局仍用普通 React 写;hook 不管输入框,需要你自己 useState

默认 transport 指向 POST /api/chat。自定义 URL、Header、body 时用 DefaultChatTransport(从 ai 导入)。


最小完整页

'use client';

import { useChat } from '@ai-sdk/react';
import { DefaultChatTransport } from 'ai';
import { useState } from 'react';

export default function Page() {
  const { messages, sendMessage, status } = useChat({
    transport: new DefaultChatTransport({ api: '/api/chat' }),
  });
  const [input, setInput] = useState('');

  return (
    <>
      {messages.map((message) => (
        <div key={message.id}>
          {message.role === 'user' ? 'User: ' : 'AI: '}
          {message.parts.map((part, index) =>
            part.type === 'text' ? <span key={index}>{part.text}</span> : null,
          )}
        </div>
      ))}
      <form
        onSubmit={(e) => {
          e.preventDefault();
          if (!input.trim()) return;
          sendMessage({ text: input });
          setInput('');
        }}
      >
        <input
          value={input}
          onChange={(e) => setInput(e.target.value)}
          disabled={status !== 'ready'}
        />
        <button type="submit" disabled={status !== 'ready'}>
          Send
        </button>
      </form>
    </>
  );
}

服务端必须返回 UI Message Stream(见 快速上手createUIMessageStreamResponse)。两边协议不一致时,界面会一直转圈或报错。


消息形状:parts

每条 UIMessageidrolepartsparts 是有序数组,可能含:

part.type含义
text普通文本,读 part.text
tool-weather名为 weather 的工具(模式:tool-{toolName}
推理 / 文件 / 自定义 data-*见官方 Chatbot 文档

旧代码里的 message.content 不要再当主路径。工具结果、推理 token 都走 parts


status 与交互

status含义UI 建议
submitted已发出,还没开始流显示 Spinner
streaming正在收 chunk显示 Stop
ready可发下一条启用输入框
error请求失败通用「出错了」+ Retry
const { status, stop, error, regenerate } = useChat();

{(status === 'submitted' || status === 'streaming') && (
  <button type="button" onClick={() => stop()}>Stop</button>
)}
{error && (
  <button type="button" onClick={() => regenerate()}>Retry</button>
)}

stop() 中止进行中的 fetch。regenerate() 让模型重写上一条助手回复。对用户只显示泛化错误,避免把服务端堆栈漏到浏览器。


改历史、节流、回调

messages / setMessages 用法接近 useState。例如按 id 删除一条:

const { messages, setMessages } = useChat();
setMessages(messages.filter((m) => m.id !== idToDelete));

React 下可用 throttle: 50(毫秒)合并渲染,避免每个 token 都触发一次重绘。

可选回调:onFinish(助手完成)、onErroronData(收到 data part)。在 onData 里抛错会中止并走 onError


请求配置

钩子级(所有请求):

useChat({
  transport: new DefaultChatTransport({
    api: '/api/custom-chat',
    headers: { Authorization: `Bearer ${token}` },
    body: { user_id: '123' },
  }),
});

headers / body 也可以是函数,用来刷新 token。单次请求的选项优先于钩子级配置。不要把密钥写进客户端代码;token 应从已登录会话读取。


同系列 hooks(知道即可)

Hook用途
useChat多轮对话(本教程主路径)
useCompletion单次补全
useObject消费 streamText + Output.object 的部分 JSON

生产聊天用 Core + UI,不要默认上实验性 RSC。见 RSC


下一步

评论