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

Channel Preview

Each row of a ChannelList is a ChannelListItem. It reads the row's values from the channel's stores, such as the title, the last message and the unread count, and renders ChannelListItemUI, the row's look, with them as props. Channel list UI explains what each value is read from.

Best practices

  • To change the look and keep the values, register your own ChannelListItemUI. To change the whole row, register a ListItem.
  • Keep a row light: it renders for every channel in the list.
  • Use the props a row gets, such as displayTitle and unread, rather than reading them from the channel again. They're reactive, and channel.data isn't.
  • Keep the row's clickable element a <button> with role="option" inside a str-chat__channel-list-item-container element. The list's arrow-key navigation moves between those.
  • To change only the avatar or the last-message line, override Avatar or SummarizedMessagePreview instead of the whole row.

Basic usage

Register your component as ChannelListItemUI. This one renders the default row, and adds a label to frozen channels:

import type { PropsWithChildren } from "react";
import type { ChannelStateData } from "stream-chat";
import type { ChannelListItemUIProps } from "stream-chat-react";
import {
  ChannelListItemUI,
  useStateStore,
  WithComponents,
} from "stream-chat-react";

const frozenSelector = ({ data }: ChannelStateData) => ({
  frozen: !!data?.frozen,
});

const RowWithFrozenLabel = (props: ChannelListItemUIProps) => {
  const { frozen } = useStateStore(props.channel.state, frozenSelector);

  return (
    <div className="channel-row">
      <ChannelListItemUI {...props} />
      {frozen && <span className="channel-row__label">Frozen</span>}
    </div>
  );
};

const overrides = { ChannelListItemUI: RowWithFrozenLabel };

export const WithFrozenLabels = ({ children }: PropsWithChildren) => (
  <WithComponents overrides={overrides}>{children}</WithComponents>
);

The Preview UI recipe builds a row from scratch.

Default preview behavior

The default ChannelListItemUI:

  • is a <button> with role="option", and aria-selected while its channel is open;
  • renders the Avatar override, ChannelAvatar by default, with displayImage and the members of a group channel;
  • shows displayTitle, and a pin icon and a mute icon when the channel is pinned or muted;
  • shows the time of the previewed message with ChannelListItemTimestamp, and an unread badge when unread is above 0;
  • renders the SummarizedMessagePreview override for the last-message line, with the sender and the delivery status of the user's own message;
  • renders the ChannelListItemActionButtons override after the button: mute, and a menu with archive, block, pin and leave. See Channel-list row actions;
  • calls onSelect when clicked, if set. Otherwise it opens the channel with openChannel(channel, { event }).

Props

ChannelListItem takes the props in the first table, and passes them on to ChannelListItemUI. ChannelListItemUI also gets the values in the second table, which ChannelListItem computes.

Prop Type Default Description
channel Channel required The row's channel.
active boolean whether the channel is open Whether the row is highlighted. ChannelListItem sets it from isChannelActive(channel.cid) unless you pass it.
activeChannel Channel none In the type, but nothing sets or reads it.
className string none Class name added to the row's button.
onSelect (event: React.MouseEvent) => void none Runs when the row is clicked, instead of opening the channel.
previewedMessage LocalMessage the channel's latest message The message the row previews. Search results pass the matched message.
Prop Type Description
accessibleLabelConfig ChannelListItemLabelConfig Not set by ChannelListItem. Pass it from your own ChannelListItemUI to the default one, to change the row's accessible name: its parts, their order, the separator, or the whole label.
displayImage string The channel's image. In a channel with two members and no image, the other member's image.
displayTitle string The channel's name. Without one: the other member's name in a channel with two members, or two other members' names in a larger one.
groupChannelDisplayInfo GroupChannelDisplayInfo The members to show in a group avatar. Its overflowCount is in the type, but the SDK leaves it undefined.
messageDeliveryStatus MessageDeliveryStatus sent, delivered or read, for the user's own previewed message. undefined for someone else's message.
muted boolean Whether the user muted the channel.
pinned boolean Whether the user pinned the channel.
unread number The user's unread messages in the channel. 0 while the channel is muted.

Delivery status and summaries

These parts and helpers are exported, to build a row that matches the default one:

Name What it does
ChannelListItemTimestamp The time of previewedMessage, formatted like the default row.
SummarizedMessagePreview The last-message line. Takes latestMessage, messageDeliveryStatus and participantCount.
useLatestMessagePreview(params) What SummarizedMessagePreview renders, as data: text, type, senderName and deliveryStatus. Takes the same params.
useChannelPreviewInfo({ channel }) displayTitle, displayImage and groupChannelDisplayInfo, reactively.
useChannelDisplayName(channel) displayTitle alone.
getChannelDisplayImage(channel, currentUserId) displayImage, read once, not reactively.
useChannelMembershipState(channel) The user's membership, with pinned_at and archived_at.
useChannelListItemContext() { channel }, for any component rendered inside a row. Throws outside one.

useLatestMessagePreview returns a type for the kind of message, such as text, image, giphy, voice, poll or deleted. A /giphy message has the giphy type, not image. Its deliveryStatus adds sending to the three values of MessageDeliveryStatus.

Hooks