import { useChannelStateContext } from "stream-chat-react";
const Component = () => {
const { messages } = useChannelStateContext();
return <div>{messages.length}</div>;
};MessageList
MessageList renders the standard scrollable list of channel messages. It consumes Channel state and actions, injects date separators when enabled, and renders unread and notification UI around the list.
By default, MessageList reads its messages from ChannelStateContext:
Best Practices
- Render
MessageListunderChannel. - Avoid passing
messagesunless you need to control the list contents directly. - Use
renderMessagesonly for structural list changes and keep it stable withuseCallbackor module scope. - Customize message actions through the
MessageActionscomponent, not through a dedicated list prop. - Preserve list semantics such as
<li>wrappers when replacing the default renderer.
Basic Usage
import {
Channel,
ChannelHeader,
MessageInput,
MessageList,
Window,
} from "stream-chat-react";
const App = () => (
<Channel>
<Window>
<ChannelHeader />
<MessageList />
<MessageInput />
</Window>
</Channel>
);If you need to render a custom message array:
const customMessages = [
// ...
];
<MessageList messages={customMessages} />;Message Grouping
MessageList groups consecutive messages by user and time. The default renderer applies grouping classes such as str-chat__li--top, str-chat__li--middle, str-chat__li--bottom, and str-chat__li--single.
You can customize grouping with the groupStyles callback or disable grouping with noGroupByUser.
Custom Message List Rendering
Use renderMessages to replace the final rendering pipeline while still reusing the SDK processing step:
import {
MessageList,
defaultRenderMessages,
type MessageRenderer,
} from "stream-chat-react";
const customRenderMessages: MessageRenderer = (options) => {
const elements = defaultRenderMessages(options);
elements.push(<li key="caught-up">You're all caught up!</li>);
return elements;
};
const CustomMessageList = () => (
<MessageList renderMessages={customRenderMessages} />
);Returned elements should have stable key values. Wrapping rendered items in <li> elements keeps the markup compatible with the default list layout.
Notifications And Unread UI
The default MessageList renders these pieces around the message list:
UnreadMessagesNotificationNewMessageNotificationScrollToLatestMessageButtonMessageListNotifications
MessageListNotifications is the notifications container. NewMessageNotification and ScrollToLatestMessageButton are separate components and are not configured through MessageListNotifications.
Props
MessageList forwards the current message UI props to the Message component it renders, including:
additionalMessageInputPropscloseReactionSelectorOnClickdisableQuotedMessagesformatDategetDeleteMessageErrorNotificationgetFlagMessageErrorNotificationgetFlagMessageSuccessNotificationgetMarkMessageUnreadErrorNotificationgetMarkMessageUnreadSuccessNotificationgetMuteUserErrorNotificationgetMuteUserSuccessNotificationgetPinMessageErrorNotificationMessagemessageActionsonlySenderCanEditonMentionsClickonMentionsHoveronUserClickonUserHoveropenThreadpinPermissionsreactionDetailsSortrenderTextretrySendMessageshowAvatarsortReactionssortReactionDetailsunsafeHTML
For custom message actions, provide a custom MessageActions component through WithComponents or pass a custom messageActions array to the list.
| Prop | Description | Type |
|---|---|---|
disableDateSeparator | Disables injected date separators. | boolean |
groupStyles | Custom callback for message grouping. | MessageListProps["groupStyles"] |
hasMore | Whether older messages can be loaded. | boolean |
head | Element rendered above the thread reply list. Used internally by Thread. | ReactElement |
headerPosition | Position where HeaderComponent should render. | number |
hideDeletedMessages | Hides deleted-message bubbles. | boolean |
hideNewMessageSeparator | Hides the separator inserted for unread incoming messages in watched but inactive channels. | boolean |
internalInfiniteScrollProps | Additional props for the internal infinite scroll component. | Partial<InfiniteScrollProps> |
jumpToLatestMessage | Loads the latest message set after the list has jumped away from it. | () => Promise<void> |
loadingMore | Whether older messages are currently loading. | boolean |
loadingMoreNewer | Whether newer messages are currently loading. | boolean |
loadMore | Loads older messages. | () => Promise<void> |
loadMoreNewer | Loads newer messages. | () => Promise<void> |
maxTimeBetweenGroupedMessages | Maximum time window for grouping messages together. | number |
messageLimit | Page size used when paginating messages. | number |
messages | Custom message array overriding ChannelStateContext.messages. | LocalMessage[] |
noGroupByUser | Disables user-based grouping. | boolean |
renderMessages | Custom render pipeline for the processed list. | MessageRenderer |
returnAllReadData | Keeps read receipts for every own message. | boolean |
reviewProcessedMessage | Lets you inspect and adjust processed list items such as date separators. | ProcessMessagesParams["reviewProcessedMessage"] |
scrolledUpThreshold | Threshold under which the list is considered close enough to the bottom to auto-scroll. | number |
showUnreadNotificationAlways | Shows the unread notification even when the unread separator is not in view. | boolean |
threadList | Marks the list as a thread list. | boolean |