# MessageList

> **Info:** This is release candidate documentation for **Stream Chat React SDK v15**. For the latest stable version, see the [latest version (v14)](https://getstream.io/chat/docs/sdk/react/).

`MessageList` renders every loaded message of the channel or the thread it sits in, and turns the user's scrolling into paginator calls. Inside a `Thread` it renders `thread.messagePaginator`, with the parent message above the replies; otherwise `channel.messagePaginator`. [Message list UI](https://getstream.io/chat/docs/sdk/react/v15/ui/components/message-list-ui/) explains what it shows, and how it differs from [`VirtualizedMessageList`](https://getstream.io/chat/docs/sdk/react/v15/component-reference/message-list/virtualizedmessagelist/).

## Best practices

- Render it inside a `Channel` or a `Thread`. It picks the paginator from there, so the same `<MessageList />` works in both.
- Switch to `VirtualizedMessageList` when the DOM gets too large: very long histories, or channels with a lot of traffic.
- Change how one message looks with the `MessageUI` override, and its actions with `MessageActions` and a `messageActionSet`. See [Message actions](https://getstream.io/chat/docs/sdk/react/v15/ui/customizing/actions/#message-actions). The list has no prop for actions.
- Declare `renderMessages`, `groupStyles` and `reviewProcessedMessage` at module scope, or wrap them in `useCallback`.
- Keep the `li` wrappers when you replace the rendering with `renderMessages`, so the markup stays a list.

## Basic usage

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

export const ChannelPanel = () => (
  <Channel channel={channel}>
    <ChannelHeader />
    <MessageList />
    <MessageComposer />
  </Channel>
);
```

In a thread, render it inside `<Thread thread={thread}>` the same way. The paginator's state, and how a component of yours picks the right one, are on [Reading state in components](https://getstream.io/chat/docs/sdk/react/v15/ui/reading-state-in-components/#which-owner-a-hook-reads).

## Message grouping

`MessageList` groups consecutive messages from the same sender. Each message gets a group style, `top`, `middle`, `bottom` or `single`, and its `li` the matching class, such as `str-chat__li--top`. A new group starts when the sender changes, after a date separator, a system message or an edited message, and at a message with reactions. A message with attachments is always `single`.

- `noGroupByUser` turns grouping off: every message is `single`.
- `maxTimeBetweenGroupedMessages` starts a new group when two messages are further apart than this many milliseconds. Without it, time doesn't split groups.
- `groupStyles` replaces the rule. It receives each message with the ones before and after it, and returns the group style.

## Custom message list rendering

`renderMessages` replaces how the processed list turns into elements. `defaultRenderMessages` is the SDK's own, so you can add to it:

```tsx
import { defaultRenderMessages, MessageList } from "stream-chat-react";
import type { MessageRenderer } from "stream-chat-react";

const renderMessagesWithFooter: MessageRenderer = (options) => [
  ...defaultRenderMessages(options),
  <li className="str-chat__li" key="caught-up">
    You're all caught up!
  </li>,
];

export const ChannelMessages = () => (
  <MessageList renderMessages={renderMessagesWithFooter} />
);
```

Give every element a stable `key`. The options include the processed messages, with date separators and the header among them, the group styles, the read and delivery data, and the components in effect.

To change the items before they render, for example to drop or add one around a message, use `reviewProcessedMessage` instead.

## Notifications and unread UI

Around the messages, `MessageList` renders:

- `UnreadMessagesNotification`, at the top of a channel's list while the unread separator is above the visible area or not loaded. Threads don't show it.
- `NewMessageNotification`, while the user is scrolled up and new messages arrive, or the list shows an older interval.
- The scroll-to-latest button, while the list isn't at the latest message.
- A `NotificationList` for the panel the list is in: `channel` or `thread`.

The first two and the notification list are override keys. The scroll-to-latest button has none. `MessageListMainPanel` replaces the element around the list and its notification list. [Jumps on screen](https://getstream.io/chat/docs/sdk/react/v15/ui/components/message-list-ui/#jumps-on-screen) explains when each one shows, and [Notification lists and panels](https://getstream.io/chat/docs/sdk/react/v15/ui/customizing/displaying-notifications/#notification-lists-and-panels) how notifications reach the list.

## Props

| Prop                            | Type                                                                                                   | Default                              | Description                                                                                                                                                                                                                                                                                                                               |
| ------------------------------- | ------------------------------------------------------------------------------------------------------ | ------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `groupStyles`                   | `(message, previousMessage, nextMessage, noGroupByUser, maxTimeBetweenGroupedMessages?) => GroupStyle` | `getGroupStyles`                     | Decides each message's group style: `""`, `"top"`, `"middle"`, `"bottom"` or `"single"`. The messages are `RenderedMessage` items.                                                                                                                                                                                                        |
| `headerPosition`                | `TimestampNS`                                                                                          | the top of the list                  | Where the `HeaderComponent` override renders: after the last message created before this time, in nanoseconds like `message.created_at`.                                                                                                                                                                                                  |
| `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.                                                                                                                                                                                                                            |
| `internalInfiniteScrollProps`   | `Partial<InfiniteScrollPaginatorProps>`, with `element` as a tag name                                  | `{ element: "div", threshold: 250 }` | Props for the scroll container. `threshold` is how close to the top or the bottom, in pixels, the list loads the next page.                                                                                                                                                                                                               |
| `loadingMore`                   | `boolean`                                                                                              | shows while an older page loads      | Whether the `LoadingIndicator` override shows above the messages while the paginator loads. Without the prop, it shows while the list loads an older page, which it starts only when the paginator has older messages and isn't already loading. `true` shows it during any load, such as a jump or a newer page; `false` never shows it. |
| `maxTimeBetweenGroupedMessages` | `number`                                                                                               | no limit                             | The longest gap, in milliseconds, between two messages of one group.                                                                                                                                                                                                                                                                      |
| `noGroupByUser`                 | `boolean`                                                                                              | `false`                              | Turns grouping off.                                                                                                                                                                                                                                                                                                                       |
| `renderMessages`                | `MessageRenderer`                                                                                      | `defaultRenderMessages`              | Turns the processed list into elements. See [Custom message list rendering](#custom-message-list-rendering).                                                                                                                                                                                                                              |
| `returnAllReadData`             | `boolean`                                                                                              | `false`                              | Gives every own message its read and delivery data. By default only the last own message gets it, so only that one shows read status.                                                                                                                                                                                                     |
| `reviewProcessedMessage`        | `ProcessMessagesParams["reviewProcessedMessage"]`                                                      |                                      | Called for each message as the list processes it. It receives `changes`, the message with any separator added before it, and returns the items to render in their place.                                                                                                                                                                  |
| `scrolledUpThreshold`           | `number`                                                                                               | `200`                                | How close to the bottom, in pixels, the list counts as at the bottom, and keeps following new messages.                                                                                                                                                                                                                                   |
| `showUnreadNotificationAlways`  | `boolean`                                                                                              | `false`                              | Also shows the unread notification while the unread separator is below the visible area.                                                                                                                                                                                                                                                  |
| `suppressAutoscroll`            | `boolean`                                                                                              | `false`                              | Stops the list from scrolling to new messages.                                                                                                                                                                                                                                                                                            |
| `withDateSeparator`             | `boolean`                                                                                              | `true`                               | 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: `additionalMessageComposerProps`, `closeReactionSelectorOnClick`, `formatDate`, `onMentionsClick`, `onMentionsHover`, `onUserClick`, `onUserHover`, `reactionDetailsSort`, `renderText`, `sortReactions` and `unsafeHTML`. They are documented on [Message](https://getstream.io/chat/docs/sdk/react/v15/component-reference/message/message/). `unsafeHTML` also renders system messages as HTML.

The list also passes `disableQuotedMessages` and `showAvatar` to each `Message`, but neither has an effect: `Message` doesn't hand `showAvatar` to the message UI, and the quote action doesn't check `disableQuotedMessages`.

## Related hooks

| Hook                                 | Returns                                                                                                                                                                                               |
| ------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `useMessageListContext()`            | the processed messages, the scroll container and `scrollToBottom`, inside `MessageList` only. See [MessageListContext](https://getstream.io/chat/docs/sdk/react/v15/component-reference/message-list/messagelistcontext/) |
| `useMessagePaginator()`              | the paginator the list renders                                                                                                                                                                        |
| `useChannel()`, `useThreadContext()` | the channel and the thread whose paginator the list renders                                                                                                                                           |
| `useStateStore(store, selector)`     | a selection of the paginator's state, such as its `items`                                                                                                                                             |
| `useMessageContext()`                | the message and its handlers, inside each message the list renders                                                                                                                                    |

`useMessagePaginator()` returns the paginator the list renders: `thread.messagePaginator` inside a `Thread`, otherwise `channel.messagePaginator`. [Reading state in components](https://getstream.io/chat/docs/sdk/react/v15/ui/reading-state-in-components/#which-owner-a-hook-reads) shows it in use. The paginator's API is on [Message paginator](https://getstream.io/chat/docs/sdk/react/v15/reference/state/message-paginator/).

---

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