# VirtualizedMessageList

`VirtualizedMessageList` renders the messages of the channel or the thread it sits in, like [`MessageList`](https://getstream.io/chat/docs/sdk/react/component-reference/message-list/messagelist/), but keeps only the messages near the visible area in the DOM, with `react-virtuoso`. [Message list UI](https://getstream.io/chat/docs/sdk/react/ui/components/message-list-ui/#messagelist-and-virtualizedmessagelist) 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 (`groupByUser`) and the typing indicator, which renders only with a `TypingIndicator` override.
- Pass `react-virtuoso` options through `additionalVirtuosoProps`.
- 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

```tsx
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](https://getstream.io/chat/docs/sdk/react/state/loading-data/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](https://getstream.io/chat/docs/sdk/react/ui/components/message-list-ui/#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. `react-virtuoso` options such as `defaultItemHeight`, `overscan` and `scrollSeekConfiguration` go here. Its `components` are merged with the list's, and its `scrollerRef` and `totalListHeightChanged` are called after the list's own handlers. With `useWindowScroll`, the floating date separator takes its date from the first rendered message, so it can lag behind the messages on screen. |
| `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. The list passes none of the props it drills to messages to the items your renderer draws; pass them to the `Message` you render.                                                                                                                                     |
| `getGroupStyles`                | `(params: GetGroupStylesParams) => GroupStyle`                    | `getGroupStyles` | Decides each message's group style. It receives the list's `groupByUser` in its argument.                                                                                                                                                                                                                                                                                                                                                                            |
| `groupByUser`                   | `boolean`                                                         | `false`          | Groups consecutive messages from the same sender.                                                                                                                                                                                                                                                                                                                                                                                                                    |
| `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.                                                                                                                                                                                                                                                                                                                                                                                                 |
| `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.                                                                                                                                                                                                                                                                                                              |
| `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.                                                                                                                                                                                                                                                                                                                                                                       |
| `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 takes these props and passes them to every `<Message/>` it renders: `closeReactionSelectorOnClick`, `formatDate`, `onMentionsClick`, `onMentionsHover`, `onUserClick`, `onUserHover`, `reactionDetailsSort`, `renderText`, `showAvatar`, `sortReactions` and `unsafeHTML`. They are documented on [Message](https://getstream.io/chat/docs/sdk/react/component-reference/message/message/). `unsafeHTML` also reaches the `MessageSystem` override, by default `<EventComponent/>`. With it set, `<EventComponent/>` renders a system message's `html` when it has one, and its `text` otherwise.

These props also reach:

- **The parent message** above the replies, in a thread.
- **The Giphy preview** that `separateGiphyPreview` renders below the messages. `GiphyPreviewMessage` is typed with `MessageProps` and passes its props to `Message`.

To the parent message and the Giphy preview, the list passes only the props you set. A `ThreadHead` or `GiphyPreviewMessage` override that sets a prop and then spreads its props, such as `<Message showAvatar {...props} />`, keeps its own value.

With `customMessageRenderer`, the parent message and the Giphy preview still get these props.

The list renders each message with the `VirtualMessage` override if one is set, and otherwise with `MessageUI`. See [ComponentContext](https://getstream.io/chat/docs/sdk/react/component-reference/channel/componentcontext/).

## Related hooks

| Hook                                 | Returns                                                                                                                                                                           |
| ------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `useVirtualizedMessageListContext()` | `scrollToBottom`, inside `VirtualizedMessageList` only. See [VirtualizedMessageListContext](https://getstream.io/chat/docs/sdk/react/component-reference/message-list/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                                                                                                                |

---

For the most recent version of this documentation, visit [https://getstream.io/chat/docs/sdk/react/component-reference/message-list/virtualizedmessagelist/](https://getstream.io/chat/docs/sdk/react/component-reference/message-list/virtualizedmessagelist/).