This is beta documentation for Stream Chat React SDK v14. For the latest stable version, see the latest version (v13) .

Channel Preview

ChannelListItemUI is the default row UI used by ChannelList. Replace it through WithComponents / ComponentContext when you need custom row rendering.

Best Practices

  • Preserve the selection handler so active channel switching keeps working.
  • Keep preview rendering lightweight because it runs for every item in the list.
  • Prefer the provided displayTitle, displayImage, and groupChannelDisplayInfo values over recomputing channel metadata yourself.
  • Use latestMessagePreview for the preview text instead of rebuilding message summaries from scratch.
  • If you build summaries from useLatestMessagePreview(), handle native giphy messages separately from ordinary images.
  • Override Avatar separately through WithComponents if only the channel image rendering needs to change.
  • Keep custom CSS aligned with the current preview structure and button semantics.

Basic Usage

To customize the row UI, register your component as the ChannelListItemUI override:

import { ChannelList, WithComponents } from "stream-chat-react";

const CustomChannelPreview = ({ latestMessagePreview }) => (
  <span>{latestMessagePreview}</span>
);

<WithComponents overrides={{ ChannelListItemUI: CustomChannelPreview }}>
  <ChannelList />
</WithComponents>;

Default Preview Behavior

ChannelListItemUI:

  • renders ChannelAvatar by default, not the plain Avatar component
  • uses displayTitle, displayImage, and groupChannelDisplayInfo from useChannelPreviewInfo()
  • renders SummarizedMessagePreview for the last-message summary
  • uses ChannelListItemTimestamp for the timestamp
  • marks the selected row with aria-pressed
  • renders ChannelListItemActionButtons, which use a context menu plus archive or mute actions depending on channel type

Props

PropDescriptionType
activeWhether the row channel is currently selected.boolean
activeChannelThe active channel from chat context.Channel
channelThe channel instance for the row.Channel
channelUpdateCountCounter value used to force a rerender when the parent list wants to refresh previews.number
classNameCustom class name merged onto the preview button.string
displayImageResolved image to display for the row. For direct messages, this can include the SDK's fallback to the other member's image.string
displayTitleResolved display title for the row. For direct messages and group channels, this can be synthesized from members.string
getLatestMessagePreviewCustom function to build the preview text.(channel: Channel, t: TranslationContextValue["t"], userLanguage: TranslationContextValue["userLanguage"], isMessageAIGenerated: ChatContextValue["isMessageAIGenerated"]) => ReactNode
groupChannelDisplayInfoResolved group-avatar data for channels with multiple visible members.GroupChannelDisplayInfo
lastMessageThe latest message currently used to build the row summary.LocalMessage
latestMessagePreviewRendered preview of the latest message.ReactNode
messageDeliveryStatusDelivery status for your own latest message. Use it when you replace the summary UI.MessageDeliveryStatus
mutedWhether the current user has muted the channel.boolean
onSelectCustom click handler for the row.(event: React.MouseEvent) => void
setActiveChannelSetter used by the default row click handler.ChatContextValue["setActiveChannel"]
unreadUnread message count for the channel.number
watchersWatcher query options forwarded when activating the channel.{ limit?: number; offset?: number }

If you need to change only the avatar rendering, override Avatar through WithComponents instead of expecting ChannelListItemUI to receive an Avatar prop.

Delivery Status And Summaries

If you build your own row, prefer reusing the SDK helpers that match the default preview:

  • ChannelListItemTimestamp
  • SummarizedMessagePreview
  • getChannelDisplayImage(channel)
  • useChannelDisplayName(channel)

That keeps custom previews aligned with the current channel title, avatar, timestamp, and delivery-status behavior without depending on removed standalone status-icon exports.

If you go lower-level and switch on useLatestMessagePreview().type, include a giphy case. Native giphy messages now resolve to their own preview type instead of being folded into image.