Channel preview
Each row of a ChannelList is a ChannelPreview. It reads the row's values from the channel's stores, such as whether the channel is muted, the unread count and the latest message, wraps the row in its swipe actions, and renders the ChannelPreview override key with those values as props. The default for that key is ChannelPreviewView, the row's look. Channel list UI explains what each value is read from.
The exported ChannelPreview component and the ChannelPreview override key are different things. The component is the row wrapper that ChannelListView renders for each channel, and it has no key. The key is the row's content, which the wrapper renders: ChannelPreviewView by default.
Best practices
- To change the look and keep the values, register your own component as the
ChannelPreviewkey. It gets the same props asChannelPreviewView, and can renderChannelPreviewViewitself. - To change only one part, such as the title or the unread badge, override that part's key instead of the whole row. See Parts.
- Keep a row light, since it renders for every channel in the list.
- Use the props a row gets, such as
unreadandlastMessage, rather than reading them from the channel again. They're reactive, andchannel.dataisn't. - A row of your own that doesn't render
ChannelPreviewViewcallsonSelectfromuseChannelsContext()itself. The SDK doesn't export the registry of open swipe actions, so such a row can't close them on a tap as the default does.
Basic usage
The default row shows the time of the latest message from the timestamp.ChannelPreviewStatus translation key. ChannelPreviewView takes formatLatestMessageDate to format it yourself, but ChannelPreview doesn't pass it, so register a row that does:
import type { PropsWithChildren } from "react";
import { ChannelPreviewView, WithComponents } from "stream-chat-react-native";
import type {
ChannelPreviewViewProps,
ComponentOverrides,
} from "stream-chat-react-native";
const formatLatestMessageDate = (date: Date) =>
date.toLocaleDateString(undefined, { day: "numeric", month: "short" });
const RowWithShortDate = (props: ChannelPreviewViewProps) => (
<ChannelPreviewView
{...props}
formatLatestMessageDate={formatLatestMessageDate}
/>
);
const overrides: ComponentOverrides = { ChannelPreview: RowWithShortDate };
export const RowsWithShortDates = ({ children }: PropsWithChildren) => (
<WithComponents overrides={overrides}>{children}</WithComponents>
);The Preview UI cookbook builds a row from scratch.
What a row does
ChannelPreview:
- reads
muted,pinnedandunreadfromchannel.state, andlastMessagefromchannel.messagePaginator.aggregateState.unreadis the current user's unread count, and0while the channel is muted. - replaces
lastMessagewith its translation into the user's language, when the message has one. - subscribes the channel's composer to draft events, so the row shows the user's draft.
- wraps the row in its swipe actions, unless
swipeActionsEnabledonChannelListisfalse.
The default ChannelPreviewView:
- is a
Pressable. A tap closes any open swipe actions in the list, or callsonSelect(channel)when none are open. - renders the avatar at the start, and the title with the muted and pinned icons, the time of the latest message and the unread badge on its first line.
- renders the message line on its second line: who is typing, the draft, "No messages yet", the poll's label, "Message failed to send", or the latest message after its delivery status, the first that applies.
- places the muted and pinned icons after the title, or at the end of the message line, as
mutedStatusPositionandpinnedStatusPositionsay. - is memoized, so it renders again only when one of its props changes.
Props
ChannelPreview takes these props:
| Prop | Type | Default | Description |
|---|---|---|---|
channel |
Channel |
required | The row's channel. |
client |
StreamChat |
the client from ChatContext |
The client the row reads the current user's id from, to find the user's unread count. |
The ChannelPreview key, ChannelPreviewView by default, gets these props. ChannelPreview passes channel, muted, pinned, unread and lastMessage; ChannelPreviewView reads the rest from ChannelsContext unless you pass them.
| Prop | Type | Default | Description |
|---|---|---|---|
channel |
Channel |
required | The row's channel. |
formatLatestMessageDate |
(date: Date) => string |
Formats the time of the latest message. Without it, the row uses the timestamp.ChannelPreviewStatus translation: the time today, "Yesterday", the weekday within the last week, and the date before that. |
|
lastMessage |
LastMessageType |
The latest message of the channel, translated when the message has a translation. LastMessageType is LocalMessage | MessageResponse. |
|
maxUnreadCount |
number |
from ChannelsContext |
The highest count the unread badge shows. |
muted |
boolean |
Whether the current user muted the channel. | |
mutedStatusPosition |
'trailingBottom' | 'inlineTitle' |
from ChannelsContext |
Where the muted icon shows: after the title, or at the end of the message line. |
onSelect |
(channel: Channel) => void |
from ChannelsContext |
Called with the channel when the row is tapped while no swipe actions are open. |
pinned |
boolean |
Whether the current user pinned the channel. | |
pinnedStatusPosition |
'trailingBottom' | 'inlineTitle' |
from ChannelsContext |
Where the pinned icon shows: after the title, or at the end of the message line. |
unread |
number |
The current user's unread messages in the channel. 0 while the channel is muted. |
Parts
ChannelPreviewView renders each part through an override key, with these props:
| Override key | Default | Gets | Shows |
|---|---|---|---|
ChannelPreviewAvatar |
ChannelAvatar |
channel, size: 'xl' |
The channel's image, or its members' avatars |
ChannelPreviewTitle |
ChannelPreviewTitle |
channel |
The channel's display name. The default also takes a title that replaces it. |
ChannelPreviewMutedStatus |
ChannelPreviewMutedStatus |
nothing | The muted icon |
ChannelPreviewPinnedStatus |
ChannelPreviewPinnedStatus |
nothing | The pinned icon |
ChannelPreviewStatus |
ChannelPreviewStatus |
channel, formatLatestMessageDate, lastMessage |
The time of the latest message |
ChannelPreviewUnreadCount |
ChannelPreviewUnreadCount |
channel, maxUnreadCount, unread |
The unread badge, hidden at 0 |
ChannelPreviewMessage |
ChannelPreviewMessage |
channel, lastMessage |
The message line |
ChannelPreviewMessage renders three more keys:
| Override key | Default | Gets | Shows |
|---|---|---|---|
ChannelPreviewTypingIndicator |
ChannelPreviewTypingIndicator |
channel, usersTyping |
Who is typing, in place of the message line |
ChannelPreviewLastMessage |
ChannelLastMessagePreview |
message |
The text of the latest message, or of the draft |
ChannelPreviewMessageDeliveryStatus |
ChannelMessagePreviewDeliveryStatus |
channel, message |
The sent, delivered or read mark of the user's own latest message, or the sender's name before another member's message in a group channel |
Every default is exported under the name in the Default column, so a replacement can render it and add to it.
Related hooks
useChannelPreviewDisplayName(channel)returns the title the default row shows.useChannelPreviewDisplayPresence(channel)returnstruewhen the channel has two members and the other one is online.useChannelTypingState({ channel })returns who is typing in the channel.useChannelPreviewDraftMessage({ channel })returns the user's draft in the channel.useIsChannelMuted(channel)returns the channel's mute status,{ muted, createdAt, expiresAt }, anduseIsChannelPinned(channel)whether the user pinned it.
Their signatures are on Channel preview hooks.