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

MessageFlashList

MessageFlashList renders the same messages as 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 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 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

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.

The hooks are the same as for MessageList: see MessageList.