Skip to content

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:

import { useChannelStateContext } from "stream-chat-react";

const Component = () => {
  const { messages } = useChannelStateContext();

  return <div>{messages.length}</div>;
};

Best Practices

  • Render MessageList under Channel.
  • Avoid passing messages unless you need to control the list contents directly.
  • Use renderMessages only for structural list changes and keep it stable with useCallback or module scope.
  • Customize message actions through the MessageActions component, not through a dedicated list prop.
  • Preserve list semantics such as <li> wrappers when replacing the default renderer.

Basic Usage

import {
  Channel,
  ChannelHeader,
  MessageComposer,
  MessageList,
  Window,
} from "stream-chat-react";

const App = () => (
  <Channel>
    <Window>
      <ChannelHeader />
      <MessageList />
      <MessageComposer />
    </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:

  • UnreadMessagesNotification
  • NewMessageNotification
  • ScrollToLatestMessageButton
  • NotificationList

NotificationList renders panel-scoped client notifications. NewMessageNotification, UnreadMessagesNotification, and ScrollToLatestMessageButton are separate components. If you need layout control around the whole stack, override MessageListMainPanel.

Props

MessageList forwards the current message UI props to the Message component it renders, including:

  • additionalMessageComposerProps
  • closeReactionSelectorOnClick
  • disableQuotedMessages
  • formatDate
  • Message
  • messageActions
  • onMentionsClick
  • onMentionsHover
  • onUserClick
  • onUserHover
  • openThread
  • reactionDetailsSort
  • renderText
  • retrySendMessage
  • showAvatar
  • sortReactions
  • unsafeHTML

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