自訂 Footer
用 renderFooter 完全取代預設 footer。當你需要客製整個輸入區(例如改成
單行 input、加上自製語音按鈕、改變排版邏輯)時用它;只是想在送出按鈕
後面加額外按鈕,請改用 footerEndActions。
完全取代 Footer
用 renderFooter 直接接管 footer 區域:內建 textarea、送出按鈕、圖片 / 文件上傳、export、麥克風、drag-drop、IME 保護、footerEndActions 都不再渲染,整塊由 renderer 自己負責。
- 用 useAsgardContext() 取得 sendMessage / isConnecting / inputPlaceholder
- 用 pendingInputValue + setPendingInputValue 接收外部塞入的文字(例如 quick prompt)
- isConnecting 時禁用送出,避免重複送訊息
- IME 組字保護:Enter 在 isComposing 時不送出
聊天機器人載入中…
取代的內建功能
renderFooter 是完全取代而不是疊加:
- 內建
textarea與自動高度 - 送出按鈕、麥克風按鈕
- 圖片上傳、文件上傳、export 對話紀錄
- Drag-and-drop 上傳整合
- IME 組字保護(避免中文打字途中按 Enter 直接送出)
footerEndActions槽位
以上元件全部不再渲染,由 renderer 自己負責。
程式範例
import {
Chatbot,
useAsgardContext,
type ChatbotRef,
} from "@asgard-js/react";
import { useEffect, useRef, useState } from "react";
function MyFooter() {
const {
sendMessage,
isConnecting,
pendingInputValue,
setPendingInputValue,
inputPlaceholder,
} = useAsgardContext();
const [value, setValue] = useState("");
const textareaRef = useRef<HTMLTextAreaElement>(null);
// 接收外部透過 ChatbotRef.setInputValue 塞進來的文字
useEffect(() => {
if (pendingInputValue == null) return;
setValue(pendingInputValue);
setPendingInputValue(null);
textareaRef.current?.focus();
}, [pendingInputValue, setPendingInputValue]);
const submit = () => {
const text = value.trim();
if (!text || isConnecting) return;
sendMessage?.({ text });
setValue("");
};
return (
<div className="footer">
<textarea
ref={textareaRef}
placeholder={inputPlaceholder}
value={value}
onChange={(e) => setValue(e.target.value)}
onKeyDown={(e) => {
// IME 組字途中不送出
if (
e.key === "Enter" &&
!e.shiftKey &&
!e.nativeEvent.isComposing
) {
e.preventDefault();
submit();
}
}}
rows={1}
/>
<button
onClick={submit}
disabled={!value.trim() || isConnecting}
>
送出
</button>
</div>
);
}
function Demo() {
const chatbotRef = useRef<ChatbotRef>(null);
return (
<Chatbot
ref={chatbotRef}
renderFooter={() => <MyFooter />}
{...rest}
/>
);
}
useAsgardContext 常用欄位
| 欄位 | 型別 | 說明 |
|---|---|---|
sendMessage | (params) => void | 送出訊息;undefined 代表 preview / 未連線 |
isConnecting | boolean | 是否正在等待回覆,建議用它禁用送出按鈕 |
pendingInputValue | string | null | 外部透過 ChatbotRef.setInputValue 推進來的文字 |
setPendingInputValue | (v: string | null) => void | 消化掉 pending 值後請把它清成 null |
inputPlaceholder | string | Chatbot props 傳入的 placeholder |
messages | Map<string, ConversationMessage> | 所有訊息(如果你要做 token 計數等用途) |
與 renderMenu / ChatbotRef.setInputValue 串接
這個 demo 同時用了 renderMenu 列出快速提問。按鈕透過
chatbotRef.current?.setInputValue(prompt) 把文字塞進 SDK 內部的
pendingInputValue,再由你的自訂 footer 消化掉,做到「點選 → 文字填入
輸入框 → 使用者再決定要不要送」的流程。
什麼時候不要用 renderFooter
- 只想在送出鈕旁加按鈕:用
footerEndActions, 內建邏輯完全保留。 - 完全跳過 Chatbot UI:用 Headless 模式,自己組裝整個畫面。