MUI X
ChatSubscribe to exactly the store slices you need with memoized selectors for efficient, granular rendering.
chatSelectors is a collection of memoized selectors that read from the normalized chat store. They power the built-in hooks and can also be used directly with useChatStore() for advanced subscriptions.
import { chatSelectors, useChatStore } from '@mui/x-chat/headless';
CopyCopied(or $keyC)
The following demo uses selectors for efficient rendering:
Update message 6Append one rowSelector-driven threadUpdate one controlled message from the parent to see only the matching row rerender.
Selector-driven threadselector-1 · renders 0MUI Agent
Row 1 is subscribed independently.
selector-2 · renders 0Alice
Row 2 is subscribed independently.
selector-3 · renders 0MUI Agent
Row 3 is subscribed independently.
selector-4 · renders 0Alice
Row 4 is subscribed independently.
selector-5 · renders 0MUI Agent
Row 5 is subscribed independently.
selector-6 · renders 0Alice
Row 6 is subscribed independently.
selector-7 · renders 0MUI Agent
Row 7 is subscribed independently.
selector-8 · renders 0Alice
Row 8 is subscribed independently.
selector-9 · renders 0MUI Agent
Row 9 is subscribed independently.
selector-10 · renders 0Alice
Row 10 is subscribed independently.
selector-11 · renders 0MUI Agent
Row 11 is subscribed independently.
selector-12 · renders 0Alice
Row 12 is subscribed independently.
selector-13 · renders 0MUI Agent
Row 13 is subscribed independently.
selector-14 · renders 0Alice
Row 14 is subscribed independently.
Selector referenceDirect state selectorsThese selectors read a single field from the store and return it directly:
Selector Return type Description messageIds string[] Ordered message IDs messagesById Record Message map by ID conversationIds string[] Ordered conversation IDs conversationsById Record Conversation map by ID activeConversationId string | undefined Active conversation ID isStreaming boolean Whether a stream is active hasMoreHistory boolean Whether more history can be loaded error ChatError | null Current runtime error composerValue string Current draft text composerAttachments ChatDraftAttachment[] Draft attachments Derived selectorsThese selectors combine multiple store fields and memoize the result:
Selector Return type Description messages ChatMessage[] All messages as an array (derived from IDs + map) conversations ChatConversation[] All conversations as an array activeConversation ChatConversation | undefined The active conversation record messageCount number Number of messages conversationCount number Number of conversations Parameterized selectors Selector Signature Description message (state, id: string) => ChatMessage | undefined Single message by ID conversation (state, id: string) => ChatConversation | undefined Single conversation by ID typingUserIds (state, conversationId?: string) => string[] User IDs typing in a conversation (defaults to active) Using selectors with useChatStore()The hooks useMessageIds(), useMessage(id), and others are convenience wrappers around useChatStore() + chatSelectors. When you need a custom derived value, use the store directly:
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)
Parameterized selectorsFor selectors that take an argument, pass a selector function:
function ConversationTitle({ id }: { id: string }) {
const store = useChatStore();
const conversation = useStore(store, chatSelectors.conversation, id);
return span>{conversation?.title ?? 'Untitled'}span>;
}
CopyCopied(or $keyC)
Why normalization mattersThe store keeps messages and conversations in a normalized shape (ids + byId maps) rather than flat arrays. This design has three benefits:
Point updates — Updating a single message during streaming does not rebuild the message array. Only the messagesById record changes. Stable references — The messageIds array only changes when messages are added or removed, not when their content updates. useMessageIds() stays stable during streaming. Memoized derivation — The messages selector rebuilds the array only when either messageIds or messagesById changes, and the result is reference-equal when inputs are unchanged.This is why the useMessageIds() + useMessage(id) pattern performs well for large threads — the ID list stays stable while individual rows subscribe to their own message record.
See also Hooks for the hook API that wraps these selectors. State and store for the internal state shape and controlled/uncontrolled models. Advanced store access for a demo using useChatStore() with custom selectors. Selector-driven thread for the row-level subscription pattern in action. API ChatRoot Edit this pageWas this page helpful?
•
Blog•
StoreContents
Selector referenceDirect state selectorsDerived selectorsParameterized selectorsUsing selectors with useChatStore()Parameterized selectorsWhy normalization mattersSee alsoAPIBecome a Diamond sponsorMUI stands in solidarity with Ukraine.Chat - Core selectors - MUI X,AI智能索引,全网链接索引,智能导航,网页索引
- Subscribe to exactly the store slices you need with memoized selectors for efficient, granular rendering.