# MessageFlashList

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

`MessageFlashList` renders the same messages as [`MessageList`](https://getstream.io/chat/docs/sdk/react-native/v10/component-reference/message-list/messagelist/), on `FlashList` from `@shopify/flash-list` instead of React Native's `FlatList`. It recycles cells between messages of the same shape, such as text only or with a gallery, instead of creating one per message. Inside a `Thread` it renders `thread.messagePaginator`, otherwise `channel.messagePaginator`. [Message list UI](https://getstream.io/chat/docs/sdk/react-native/v10/ui/components/message-list-ui/#messagelist-and-messageflashlist) compares the two lists.

>
> **Warning:** `MessageFlashList` is experimental: its implementation can change between releases. Test it with your app's messages before you ship it.
>

## Best practices

- Install `@shopify/flash-list` 2.1.0 or later. It's an optional peer dependency, and `MessageFlashList` throws when it isn't installed.
- Use `MessageList` unless profiling shows the list is the bottleneck. [Performance](https://getstream.io/chat/docs/sdk/react-native/v10/features/app-experience/performance/#messageflashlist) covers when it helps.
- Mind that the list isn't inverted: `HeaderComponent` is the older end, at the top of the screen, and `FooterComponent` the newer end, at the bottom. `MessageList` has them the other way round.
- Keep custom message components light, and their state out of component state where you can: a recycled cell keeps its component instance when it moves to another message.
- Pass `onThreadSelect` in a channel, as with `MessageList`.

## Basic usage

```tsx title="src/ChannelScreen.tsx"
import type { Channel as StreamChannel, Thread } from "stream-chat";
import {
  Channel,
  MessageComposer,
  MessageFlashList,
} from "stream-chat-react-native";

type ChannelScreenProps = {
  channel: StreamChannel;
  onOpenThread: (thread: Thread) => void;
};

export const ChannelScreen = ({
  channel,
  onOpenThread,
}: ChannelScreenProps) => (
  <Channel channel={channel}>
    <MessageFlashList onThreadSelect={onOpenThread} />
    <MessageComposer />
  </Channel>
);
```

In a thread, render `<MessageFlashList />` inside `<Thread thread={thread}>`.

## How it differs from MessageList

Both lists read the same contexts, render the same parts and use the same override keys. They differ in:

|                                       | `MessageList`                                        | `MessageFlashList`                        |
| ------------------------------------- | ---------------------------------------------------- | ----------------------------------------- |
| Extra list props                      | `additionalFlatListProps`                            | `additionalFlashListProps`                |
| Older end, at the top                 | `FooterComponent`                                    | `HeaderComponent`                         |
| Newer end, at the bottom              | `HeaderComponent`                                    | `FooterComponent`                         |
| A list shorter than the screen        | loads older pages until the messages fill the screen | loads older pages as the user scrolls up  |
| Layout animation                      | `animateLayout`, on by default                       | none                                      |
| The `FlatList` from `MessagesContext` | used with `animateLayout={false}`                    | not used                                  |
| `inverted`                            | a prop, `true` by default                            | not a prop: the list renders oldest first |

Each item is a `LocalMessage`. The list tells `FlashList` the item type of each message, such as `message-with-gallery`, `message-with-text` or `deleted-message`, so a cell is recycled only between messages of that type.

## Props

`MessageFlashListProps` makes every prop optional. The props marked "from" a context default to that context's value.

| Prop                          | Type                                                | Default                                                                     | Description                                                                                                                                                                                                                                                                |
| ----------------------------- | --------------------------------------------------- | --------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `additionalFlashListProps`    | `Partial<FlashListProps<LocalMessage>>`             |                                                                             | Props for the inner `FlashList`. `style` and `contentContainerStyle` are merged with the list's own, and `accessibilityActions` and `onAccessibilityAction` are combined with the list's scroll-to-bottom action. Any other key replaces the list's prop of the same name. |
| `attachmentPickerStore`       | `AttachmentPickerStore`                             | from `AttachmentPickerContext`                                              | The attachment picker's state. A touch on the list closes the picker.                                                                                                                                                                                                      |
| `channel`                     | `Channel`                                           | from `ChannelContext`                                                       | The channel whose messages the list renders.                                                                                                                                                                                                                               |
| `client`                      | `StreamChat`                                        | from `ChatContext`                                                          | The client.                                                                                                                                                                                                                                                                |
| `closePicker`                 | `() => void`                                        | from `AttachmentPickerContext`                                              | Closes the attachment picker.                                                                                                                                                                                                                                              |
| `disabled`                    | `boolean`                                           | from `ChannelContext`                                                       | `true` while the channel is frozen. When it turns `true`, the scroll-to-bottom button hides.                                                                                                                                                                               |
| `disableTypingIndicator`      | `boolean`                                           | from `MessagesContext`                                                      | Leaves the typing indicator out of the default `FooterComponent`.                                                                                                                                                                                                          |
| `FooterComponent`             | `React.ComponentType`                               | the newer-end loading indicator, then the typing indicator                  | Rendered at the newer end, the bottom of the screen. It receives no props, and a replacement removes the typing indicator unless it renders one.                                                                                                                           |
| `hasPendingInitialTargetLoad` | `() => boolean`                                     | from `ChannelContext`                                                       | Set by `Channel` and `Thread`, and returns `true` while a jump to a message, such as the one the channel was opened at, is pending. The list doesn't scroll to the newest message meanwhile.                                                                               |
| `HeaderComponent`             | `React.ComponentType<{ loadingMore?: boolean }>`    | `ThreadFooterComponent` in a thread, `InlineLoadingMoreIndicator` otherwise | Rendered at the older end, the top of the screen, and receives `loadingMore`. In a thread the default renders the parent message, so a replacement replaces it too.                                                                                                        |
| `hideStickyDateHeader`        | `boolean`                                           | from `ChannelContext`                                                       | Turns off the sticky date header.                                                                                                                                                                                                                                          |
| `isLiveStreaming`             | `boolean`                                           | `false`                                                                     | Tunes the list for many messages a second: list updates are batched to one per frame, and scroll events arrive every 16 ms. Experimental.                                                                                                                                  |
| `markRead`                    | `(options?: MarkReadFunctionOptions) => void`       | `useMarkRead(channel)`                                                      | Marks the channel read. In a channel, the list calls it when a new message arrives while the user views the latest messages, and, with `updateChannelUnreadState: false`, when the user taps the scroll-to-bottom button. The unread notification calls it when closed.    |
| `messageInputFloating`        | `boolean`                                           | from `MessageInputContext`                                                  | With `true`, the list pads its content by the composer's height and lifts its floating parts above the composer.                                                                                                                                                           |
| `messageInputHeightStore`     | `MessageInputHeightStore`                           | from `MessageInputContext`                                                  | The store holding the composer's height.                                                                                                                                                                                                                                   |
| `myMessageTheme`              | `DeepPartial<Theme>`                                | from `MessagesContext`                                                      | A theme merged over the current one for the user's own messages.                                                                                                                                                                                                           |
| `noGroupByUser`               | `boolean`                                           | `true` when `Channel` has `enableMessageGroupingByUser={false}`             | Turns grouping off. The list combines it with the `Channel` setting, so `false` doesn't turn grouping on when `Channel` turned it off.                                                                                                                                     |
| `onListScroll`                | `ScrollViewProps['onScroll']`                       |                                                                             | Called with every scroll event.                                                                                                                                                                                                                                            |
| `onThreadSelect`              | `(thread: Thread) => void`                          |                                                                             | Called with the message's `Thread` when the user presses a message's replies button or picks the thread reply action. Render it in a `<Thread thread={thread}>`.                                                                                                           |
| `pendingUploadsEnabled`       | `boolean`                                           | `messageComposer.attachments.pendingUploadsEnabled`                         | With `true`, the list's `NotificationList` leaves out the notifications of canceled uploads.                                                                                                                                                                               |
| `readEvents`                  | `boolean`                                           | from `OwnCapabilitiesContext`                                               | Whether the user can send read events. Without them the unread notification shows only when the channel counts unread messages locally.                                                                                                                                    |
| `setFlatListRef`              | `(ref: FlashListRef<LocalMessage> \| null) => void` |                                                                             | Receives the ref of the inner `FlashList`.                                                                                                                                                                                                                                 |
| `thread`                      | `Thread`                                            | from `ThreadContext`                                                        | The thread whose replies the list renders.                                                                                                                                                                                                                                 |

## Related hooks

The hooks are the same as for `MessageList`: see [MessageList](https://getstream.io/chat/docs/sdk/react-native/v10/component-reference/message-list/messagelist/#related-hooks).

---

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