Info:
This is release candidate documentation for Stream Chat React SDK v15. For the latest stable version, see the latest version (v14).

VirtualizedMessageList

VirtualizedMessageList renders the messages of the channel or the thread it sits in, like MessageList, but keeps only the messages near the visible area in the DOM, with react-virtuoso. Message list UI compares the two lists.

Best practices

  • Use it for very long histories, or channels with a lot of traffic such as livestreams. Otherwise MessageList is simpler.
  • Remember what is off by default here and on in MessageList: date separators (withDateSeparator), grouping by sender (shouldGroupByUser) and the typing indicator, which renders only with a TypingIndicator override.
  • Pass react-virtuoso options through additionalVirtuosoProps, rather than the deprecated defaultItemHeight, overscan and scrollSeekPlaceHolder props.
  • Keep message UIs light. The list mounts and unmounts them as the user scrolls, and measures each one.
  • Don't rely on a message's DOM node: it exists only while the message is near the visible area.

Basic usage

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

export const LivestreamPanel = () => (
  <Channel channel={channel}>
    <ChannelHeader />
    <VirtualizedMessageList
      additionalVirtuosoProps={{ defaultItemHeight: 60 }}
      stickToBottomScrollBehavior="auto"
      withDateSeparator
    />
    <MessageComposer />
  </Channel>
);

defaultItemHeight gives the list a height to estimate with before it measures the messages. stickToBottomScrollBehavior="auto" follows new messages without a smooth scroll, which keeps up with a fast channel.

Scroll behavior

  • Opening. The list opens at the latest message, with its end in view. After a jump, it opens with the target message in the middle.
  • Following new messages. While the user is at the bottom, the list follows new messages with stickToBottomScrollBehavior. When the user sends a message, the list scrolls to it even if they were scrolled up. It doesn't follow while it shows an older window, or with suppressAutoscroll.
  • Loading pages. Reaching the top loads older messages. Reaching the bottom of an older interval loads newer ones.
  • Coming back. With scrollToLatestMessageOnFocus, the list scrolls to the latest message when the window regains focus after messages arrived in the background.

How the paginator holds intervals of messages is on Message paginators.

Notifications and unread UI

Like MessageList, the list renders the unread separator, UnreadMessagesNotification in a channel, NewMessageNotification, the scroll-to-latest button, and a NotificationList for its panel. Two parts differ:

  • The typing indicator renders below the messages only when you register a TypingIndicator override.
  • A Giphy preview renders with GiphyPreviewMessage below the messages when separateGiphyPreview is on.

Jumps on screen explains when the floating elements show.

Props

Prop Type Default Description
additionalVirtuosoProps VirtuosoProps from react-virtuoso Props for the underlying Virtuoso, applied over the list's own. Its components are merged with the list's, and its scrollerRef and totalListHeightChanged are called after the list's own handlers.
closeReactionSelectorOnClick boolean Closes the reaction selector once a reaction is picked.
customMessageRenderer (messageList: RenderedMessage[], index: number) => ReactElement Renders each item in place of the list's own renderer, which renders date separators, system messages, the unread separator and Message. It receives the processed list and the item's index.
defaultItemHeight number Deprecated: use additionalVirtuosoProps.defaultItemHeight. The height the list estimates with before it measures the items.
groupStyles (message, previousMessage, nextMessage, noGroupByUser, maxTimeBetweenGroupedMessages?) => GroupStyle getGroupStyles Decides each message's group style. The list passes noGroupByUser as the opposite of shouldGroupByUser.
hideDeletedMessages boolean false Leaves deleted messages out of the list.
hideNewMessageSeparator boolean false Turns off the date separator added before the first message that arrived since the user last read the channel.
maxTimeBetweenGroupedMessages number no limit The longest gap, in milliseconds, between two messages of one group.
overscan number 0 Deprecated: use additionalVirtuosoProps.overscan. Extra content to render beyond the visible area.
returnAllReadData boolean false Gives every own message its read and delivery data. By default only the last own message gets it.
reviewProcessedMessage ProcessMessagesParams["reviewProcessedMessage"] Called for each message as the list processes it. It returns the items to render in place of changes, the message with any separator added before it.
scrollSeekPlaceHolder ScrollSeekConfiguration & { placeholder: ComponentType<ScrollSeekPlaceholderProps> } Deprecated: use additionalVirtuosoProps.scrollSeekConfiguration and additionalVirtuosoProps.components.ScrollSeekPlaceholder. Renders placeholders while the user scrolls fast.
scrollToLatestMessageOnFocus boolean false Scrolls to the latest message when the window regains focus, if messages arrived while it was in the background.
separateGiphyPreview boolean false Renders a Giphy preview with GiphyPreviewMessage below the messages, instead of in the list.
shouldGroupByUser boolean false Groups consecutive messages from the same sender.
showUnreadNotificationAlways boolean false Also shows the unread notification while the unread separator is below the visible area.
stickToBottomScrollBehavior "smooth" | "auto" "smooth" How the list follows new messages while at the bottom. "auto" jumps without animation, for channels with a lot of traffic.
suppressAutoscroll boolean false Stops the list from following new messages.
withDateSeparator boolean false Adds date separators between days, and the floating date at the top while scrolling.

The list also passes these props to every Message it renders: additionalMessageComposerProps, formatDate, reactionDetailsSort, renderText and sortReactions. They are documented on Message.

The list also passes showAvatar to each Message, but Message doesn't hand it to the message UI, so it has no effect.

The list renders each message with the VirtualMessage override if one is set, and otherwise with MessageUI. See ComponentContext.

Hook Returns
useVirtualizedMessageListContext() scrollToBottom, inside VirtualizedMessageList only. See VirtualizedMessageListContext
useMessagePaginator() the paginator the list renders: thread.messagePaginator inside a Thread, otherwise channel.messagePaginator
useChannel(), useThreadContext() the channel and the thread whose paginator the list renders
useStateStore(store, selector) a selection of the paginator's state
useMessageContext() the message and its handlers, inside each message the list renders