温馨提示:本站仅提供公开网络链接索引服务,不存储、不篡改任何第三方内容,所有内容版权归原作者所有
AI智能索引来源:http://www.mui.com/x/react-chat/core/hooks/
点击访问原文链接

Chat - Core hooks - MUI X

Chat - Core hooks - MUI XSkip to content🚀 Material UI and MUI X v9 are out! Check out the announcement blogpost.Search…

MUI X

Chatv9.0.0-alpha.8What's new in MUI XIntroductionCommon conceptsData GridDate and Time PickersChartsTree ViewSchedulerPreviewChatPreviewMigration + Chat - Core hooks

Read chat state and trigger runtime actions through hooks scoped to exactly the data your component needs.

The core package exposes nine public hooks. Each one subscribes to a specific slice of the normalized chat store, so your components only re-render when their own data changes.

import {
useChat,
useChatComposer,
useChatStatus,
useMessageIds,
useMessage,
useConversations,
useConversation,
useChatStore,
useChatPartRenderer,
} from '@mui/x-chat/headless';
CopyCopied(or $keyC)

All hooks must be called inside a .

The following demo shows hooks in action inside a minimal custom chat:

Minimal headless chatIdle

Send the first message to start the thread.

useChat()

The all-in-one orchestration hook. It returns both the public state fields and every runtime action in a single object.

State Field Type Description messages ChatMessage[] All messages in the active conversation conversations ChatConversation[] All conversations activeConversationId string | undefined Currently active conversation isStreaming boolean Whether a response is being streamed hasMoreHistory boolean Whether older messages can be loaded error ChatError | null Current error state Actions Method Signature Description sendMessage (input: UseChatSendMessageInput) => Promise Send a user message stopStreaming () => void Abort the active stream loadMoreHistory () => Promise Load older messages setActiveConversation (id: string | undefined) => Promise Switch conversations retry (messageId: string) => Promise Retry a failed message setError (error: ChatError | null) => void Update the error state addToolApprovalResponse (input: ChatAddToolApproveResponseInput) => Promise Approve or deny a tool call UseChatSendMessageInput

When calling sendMessage, the input object has the following shape:

interface UseChatSendMessageInput {
id?: string; // optional custom message ID
conversationId?: string; // target conversation
parts: ChatMessagePart[]; // message content
metadata?: ChatMessageMetadata; // app-specific metadata
author?: ChatUser; // user identity
createdAt?: ChatDateTimeString; // optional timestamp
attachments?: ChatDraftAttachment[]; // file attachments
}
CopyCopied(or $keyC) Usage
function Thread() {
const { messages, sendMessage, isStreaming } = useChat();

return (
div>
{messages.map((msg) => (
div key={msg.id}>
{msg.parts[0]?.type === 'text' ? msg.parts[0].text : null}
div>
))}
button
disabled={isStreaming}
onClick={() =>
sendMessage({
parts: [{ type: 'text', text: 'Hello!' }],
})
}
>
Send
button>
div>
);
}
CopyCopied(or $keyC)

useChat() is the fastest way to get started, but it subscribes to multiple store slices at once. For large threads or performance-sensitive trees, prefer the narrower hooks below.

useChatComposer()

Manages draft text, file attachments, and submission behavior.

Field Type Description value string Current draft text setValue (value: string) => void Update draft text attachments ChatDraftAttachment[] Draft file attachments addAttachment (file: File) => void Add a file attachment removeAttachment (localId: string) => void Remove an attachment by local ID clear () => void Clear draft text and all attachments submit () => Promise Send the composed message isSubmitting boolean Whether a stream is active (blocks new submissions) Preview URLs

When you add an image attachment, useChatComposer() automatically creates an object URL for previewing the image. The hook revokes these URLs when the attachment is removed, the composer is cleared, or the component unmounts. You do not need to manage URL lifecycle manually.

IME-safe submission

The submit method blocks when the user is in an active IME composition session (common for East Asian input methods). It also blocks when a stream is already active, preventing accidental double sends.

Usage
function DraftArea() {
const composer = useChatComposer();

return (
form
onSubmit={(e) => {
e.preventDefault();
composer.submit();
}}
>
input
value={composer.value}
onChange={(e) => composer.setValue(e.target.value)}
/>
button type="submit" disabled={composer.isSubmitting}>
Send
button>
form>
);
}
CopyCopied(or $keyC) useChatStatus()

A lightweight hook for status indicators, loading spinners, and error banners.

Field Type Description isStreaming boolean Whether a response is being streamed hasMoreHistory boolean Whether older messages can be loaded error ChatError | null Current error state typingUserIds string[] IDs of users currently typing in the active conversation

Use this hook when you need to show a status chip, typing indicator, or error banner without subscribing to the full message list.

function StatusBar() {
const { isStreaming, typingUserIds, error } = useChatStatus();

return (
div>
{isStreaming && span>Assistant is responding…span>}
{typingUserIds.length > 0 && span>{typingUserIds.length} typing…span>}
{error && span>{error.message}span>}
div>
);
}
CopyCopied(or $keyC) useMessageIds() and useMessage(id)

Row-level subscriptions for efficient thread rendering.

useMessageIds() returns string[] — the ordered list of message IDs. useMessage(id) returns ChatMessage | null — a single message by ID.

The pattern works like this: the parent component calls useMessageIds() and renders a list of row components. Each row calls useMessage(id) to subscribe to its own message. When a single message updates during streaming, only that row re-renders — the parent and sibling rows stay untouched.

function Thread() {
const messageIds = useMessageIds();

return (
div>
{messageIds.map((id) => (
MessageRow key={id} id={id} />
))}
div>
);
}

function MessageRow({ id }: { id: string }) {
const message = useMessage(id);
if (!message) return null;

return (
div>{message.parts[0]?.type === 'text' ? message.parts[0].text : null}div>
);
}
CopyCopied(or $keyC)

This is the recommended pattern for threads with more than a handful of messages.

useConversations() and useConversation(id)

Conversation-level subscriptions following the same pattern as messages.

useConversations() returns ChatConversation[] — all conversations. useConversation(id) returns ChatConversation | null — a single conversation by ID.
function Sidebar() {
const conversations = useConversations();

return (
ul>
{conversations.map((c) => (
li key={c.id}>{c.title}li>
))}
ul>
);
}
CopyCopied(or $keyC) useChatStore()

Returns the underlying ChatStore instance.

This is the escape hatch for advanced use cases that need direct store access — custom selectors, store subscriptions outside React render, or integration with external state management.

import { useChatStore, chatSelectors } from '@mui/x-chat/headless';
import { useStore } from '@mui/x-internals/store';

function MessageCounter() {
const store = useChatStore();
const count = useStore(store, chatSelectors.messageCount);

return span>{count} messagesspan>;
}
CopyCopied(or $keyC) useChatPartRenderer(partType)

Looks up a registered renderer for a specific message part type.

function useChatPartRendererTPartType extends ChatMessagePart['type']>(
partType: TPartType,
): ChatPartRendererExtractChatMessagePart, { type: TPartType }>> | null;
CopyCopied(or $keyC)

Returns null if no renderer is registered for the given part type. Renderers are registered through the partRenderers prop on ChatProvider.

function CustomPart({ part, message, index }) {
const renderer = useChatPartRenderer(part.type);

if (renderer) {
return renderer({ part, message, index });
}

return span>Unknown part type: {part.type}span>;
}
CopyCopied(or $keyC) Choosing the right hook Goal Hook Prototype or small surface useChat() Efficient thread with many messages useMessageIds() + useMessage(id) Conversation sidebar useConversations() or useConversation(id) Custom draft area with attachments useChatComposer() Status indicator, typing, or error banner useChatStatus() Custom selector or store subscription useChatStore() + chatSelectors Registered part renderer lookup useChatPartRenderer(partType) See also Selectors for the full selector API and advanced store subscriptions. State and store for ChatProvider props and the controlled/uncontrolled model. Minimal core chat for the smallest working demo. Selector-driven thread for the useMessageIds() + useMessage(id) pattern in action. Composer for useChatComposer() with attachments. API ChatRoot Edit this page

Was this page helpful?

Blog

Store

Contents

useChat(​)StateActionsUseChatSendMessageInputUsageuseChatComposer(​)Preview URLsIME-safe submissionUsageuseChatStatus(​)useMessageIds(​) and useMessage(​id)useConversations(​) and useConversation(​id)useChatStore(​)useChatPartRenderer(​partType)Choosing the right hookSee alsoAPIBecome a Diamond sponsorMUI stands in solidarity with Ukraine.Search…

Chat - Core hooks - MUI X,AI智能索引,全网链接索引,智能导航,网页索引

    Read chat state and trigger runtime actions through hooks scoped to exactly the data your component needs.