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

MessageList

MessageList renders the loaded messages of the channel or the thread it sits in, in an inverted FlatList, 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 explains what it shows, and how it differs from MessageFlashList.

Best practices

  • Render it inside a Channel or a Thread. It reads the paginator, the composer's height and the message settings from the contexts they provide, so the same <MessageList /> works in both.
  • Pass onThreadSelect in a channel. The replies button and the thread reply action call it with the message's Thread, and do nothing without it.
  • Change how one message looks with the MessageItemView override, and the actions with messageActions on Channel. See Message actions. The list has no prop for either.
  • Declare the components you pass, such as FooterComponent and HeaderComponent, outside the component that renders the list, and keep additionalFlatListProps stable.
  • Use setFlatListRef to reach the FlatList, not a ref in additionalFlatListProps.

Basic usage

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

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

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

In a thread, render it inside <Thread thread={thread}> the same way, without onThreadSelect. How a component of yours reads the paginator the list renders is on Reading state in components.

Message grouping

The list groups consecutive messages from the same user. Each message gets a group style, top, middle, bottom or single, which decides its padding, its bubble corners, and whether the avatar and the footer with the time show: only the last message of a group, bottom or single, shows them, and a message that is still sending or failed keeps its footer.

  • enableMessageGroupingByUser={false} on Channel, or noGroupByUser on the list, turns grouping off. Every message then gets an empty group style, so no message counts as the last of its group: no message shows the avatar, and only a message that is sending or failed shows the footer with the time.
  • maxTimeBetweenGroupedMessages on Channel starts a new group when two messages are further apart than this many milliseconds.
  • getMessageGroupStyle on Channel replaces the rule. It receives the message, its neighbors and the date separators around it, and returns the group styles. The default is the exported getGroupStyle.

What the list renders

Around the messages, the list renders:

Part When Override key
The older-end indicator, under the parent message in a thread the indicator while an older page loads, the parent message always none, the FooterComponent prop
The newer-end indicator and the typing indicator while a newer page loads, and while someone types none, the HeaderComponent prop
StickyHeader while the list has messages, unless hideStickyDateHeader is set StickyHeader
ScrollToBottomButton while the list isn't at the latest message, or the latest messages aren't loaded ScrollToBottomButton
UnreadMessagesNotification in a channel, while the last read message is above the screen UnreadMessagesNotification
NetworkDownIndicator while the device is offline or the connection is down NetworkDownIndicator
The composer's suggestion list while the composer shows suggestions AutoCompleteSuggestionList
The NotificationList of the channel or thread while it has notifications NotificationList
EmptyStateIndicator with listType="message", in place of the list in a channel with no messages EmptyStateIndicator
MessageListLoadingIndicator with listType="message", in place of the list while the first page loads MessageListLoadingIndicator

For each message the list renders the date separator when a day starts, the Message override, and the unread separator under the last read message. A system message renders MessageSystem instead. Floating controls explains when each control shows, and Separators the separators.

Props

MessageListProps makes every prop optional. The props marked "from" a context default to that context's value, so you set them only to override it.

Prop Type Default Description
additionalFlatListProps Partial<FlatListProps<MessageListItemWithNeighbours>> Props for the inner FlatList. 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, onLayout and onContentSizeChange included. Each item is { message, previousMessage, nextMessage }.
animateLayout boolean true Animates layout changes with a Reanimated layout transition. With false, the list renders the FlatList from MessagesContext instead.
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 HeaderComponent.
FlatList typeof FlatList from MessagesContext The list component the list renders when animateLayout is false. React Native's FlatList unless Channel sets another.
FooterComponent 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.
HeaderComponent 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.
hideStickyDateHeader boolean from ChannelContext Turns off the sticky date header.
inverted boolean true Sets inverted on the FlatList. The list's paging and scroll handling assume an inverted list.
isLiveStreaming boolean false Tunes the list for many messages a second: list updates are batched to one per frame, the list keeps following new messages from up to 300 points away instead of 10, scroll events arrive every 16 ms, and FlatList's strictMode is on from React Native 0.87. 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: FlatListType<MessageListItemWithNeighbours> | null) => void Receives the ref of the inner FlatList.
thread Thread from ThreadContext The thread whose replies the list renders.

MessageListItemWithNeighbours, AttachmentPickerStore and MessageInputHeightStore aren't exported, so type a callback that receives them through MessageListProps, for example MessageListProps['setFlatListRef'].

Parts the list renders

These are the defaults of the override keys above. Replace one with WithComponents; Overriding components explains how. StickyHeader and UnreadMessagesNotification aren't exported, so a replacement can't wrap them.

InlineDateSeparator

Renders the date above the first message of a day. The text comes from the timestamp.InlineDateSeparator translation key, and screen readers get the full date.

Prop Type Default Description
date Date The date to show.

InlineUnreadIndicator

Renders the unread separator under the last read message: "5 new messages", or "Unread Messages" without a count.

Prop Type Default Description
unreadCount number The number of unread messages, from the paginator's unread snapshot.

StickyHeader and DateHeader

StickyHeader receives the date of the topmost message on screen, formats it with the timestamp.StickyHeader translation key, and renders the DateHeader override with the result. It renders nothing without a date.

Prop Type Default Description
date Date The date to show.
dateString string | number Text shown in place of the formatted date. It's read only when date changes.

DateHeader renders the label.

Prop Type Default Description
dateString string | number The text to show.

UnreadMessagesNotification

Renders "5 unread", or "Unread Messages" without a count, with a close button. The count is the paginator's unread snapshot. The list passes markRead and an onCloseHandler that marks the channel read and hides the notification.

Prop Type Default Description
markRead (options?: MarkReadFunctionOptions) => void Marks the channel read. Called by the close button when there's no onCloseHandler.
onCloseHandler () => void calls markRead Called when the user presses the close button.
onPressHandler () => Promise<void> jumps to the first unread message Called when the user presses the notification. A failed jump publishes an error notification.

InlineLoadingMoreIndicator and InlineLoadingMoreRecentIndicator

The spinners the default FooterComponent and HeaderComponent render. They aren't override keys; pass your own FooterComponent or HeaderComponent instead.

Prop Type Default Description
loadingMore boolean InlineLoadingMoreIndicator renders a spinner while true.
Prop Type Default Description
loadingMoreRecent boolean InlineLoadingMoreRecentIndicator renders a spinner while true.

NetworkDownIndicator takes no props. It shows "Waiting for network..." while the device is offline and "Reconnecting..." while the connection to Stream is down.

Hook Returns
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, such as its items
useMessagesContext() the message settings of Channel or Thread. See MessagesContext
useMessageContext() the message and its handlers, inside each message the list renders. See MessageContext
useMarkRead(channel) the markRead callback the list uses by default
useTypingString() the "Cleo is typing" text of the list's channel or thread

The paginator's API is on Message paginator, and jumping to a message on Message paginators.