import { ChannelList, WithComponents } from "stream-chat-react";
const CustomChannelPreview = ({ latestMessagePreview }) => (
<span>{latestMessagePreview}</span>
);
<WithComponents overrides={{ ChannelListItemUI: CustomChannelPreview }}>
<ChannelList />
</WithComponents>;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, andgroupChannelDisplayInfovalues over recomputing channel metadata yourself. - Use the
latestMessagePreviewprop for the preview text instead of rebuilding message summaries from scratch. - If you render the summary yourself, use the exported
getLatestMessagePreview(channel, t, userLanguage)helper so special message types (such as nativegiphymessages) stay handled the same way as the default. - Override
Avatarseparately throughWithComponentsif 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:
Default Preview Behavior
ChannelListItemUI:
- renders
ChannelAvatarby default, not the plainAvatarcomponent - uses
displayTitle,displayImage, andgroupChannelDisplayInfofromuseChannelPreviewInfo() - renders the last-message summary, which your component receives ready-made through the
latestMessagePreviewprop - uses
ChannelListItemTimestampfor 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
| Prop | Description | Type |
|---|---|---|
active | Whether the row channel is currently selected. | boolean |
activeChannel | The active channel from chat context. | Channel |
channel | The channel instance for the row. | Channel |
channelUpdateCount | Counter value used to force a rerender when the parent list wants to refresh previews. | number |
className | Custom class name merged onto the preview button. | string |
displayImage | Resolved image to display for the row. For direct messages, this can include the SDK's fallback to the other member's image. | string |
displayTitle | Resolved display title for the row. For direct messages and group channels, this can be synthesized from members. | string |
getLatestMessagePreview | Custom function to build the preview text. | (channel: Channel, t: TranslationContextValue["t"], userLanguage: TranslationContextValue["userLanguage"], isMessageAIGenerated: ChatContextValue["isMessageAIGenerated"]) => ReactNode |
groupChannelDisplayInfo | Resolved group-avatar data for channels with multiple visible members. | GroupChannelDisplayInfo |
lastMessage | The latest message currently used to build the row summary. | LocalMessage |
latestMessagePreview | Rendered preview of the latest message. | ReactNode |
messageDeliveryStatus | Delivery status for your own latest message. Use it when you replace the summary UI. | MessageDeliveryStatus |
muted | Whether the current user has muted the channel. | boolean |
onSelect | Custom click handler for the row. | (event: React.MouseEvent) => void |
setActiveChannel | Setter used by the default row click handler. | ChatContextValue["setActiveChannel"] |
unread | Unread message count for the channel. | number |
watchers | Watcher 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:
- the
latestMessagePreviewprop — orgetLatestMessagePreview(channel, t, userLanguage)if you render the summary yourself ChannelListItemTimestampgetChannelDisplayImage(channel, currentUserId)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.
The latestMessagePreview prop and getLatestMessagePreview already apply the default summary logic for special message types — including giving native giphy messages their own preview treatment rather than folding them into the image branch — so you get that handling without inspecting message types yourself.