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

ComponentContext

ComponentContext holds the override keys: for each replaceable part of the UI, the component to render instead of the SDK's. Set keys with WithComponents, and read them with useComponentContext(). Overriding components explains how overrides apply and lists the keys by area of the screen. This page lists what each key's component receives and what renders by default.

Best practices

  • Declare the overrides object once, at module scope or with useMemo. A new object on every render re-renders every component that reads the context, each message included.
  • Put WithComponents above the component that reads the key. Chat reads NotificationAnnouncer, so that key only works from a WithComponents around Chat.
  • Use WithComponents, which merges with the overrides above it. ComponentProvider replaces them all, so use it only to reset a subtree to the defaults.
  • A custom MessageUI or VirtualMessage receives no props. It reads the message with useMessageContext(). See A custom MessageUI.
  • Before rebuilding a part, check whether the default takes what you need. For example, to change the message actions, render MessageActions with your own messageActionSet, as Message actions shows.

Basic usage

The SDK reads a key and falls back to its own component. A component of yours can do the same, so it shows whatever the app registered:

import {
  LoadingIndicator as DefaultLoadingIndicator,
  useComponentContext,
} from "stream-chat-react";

export const MembersLoading = () => {
  const { LoadingIndicator = DefaultLoadingIndicator } = useComponentContext();

  return <LoadingIndicator />;
};

useComponentContext() returns {} outside every provider. It never throws.

Registering overrides with WithComponents

WithComponents merges its overrides into the context from above. A nested one adds its keys and keeps the rest:

import type {
  Channel as StreamChannel,
  Thread as StreamThread,
} from "stream-chat";
import {
  Channel,
  ChannelHeader,
  MessageComposer,
  MessageList,
  Thread,
  ThreadHeader,
  WithComponents,
} from "stream-chat-react";
import type { DateSeparatorProps } from "stream-chat-react";

const DayOnlySeparator = ({ date }: DateSeparatorProps) => (
  <div className="str-chat__date-separator">{date.toLocaleDateString()}</div>
);

const ClosedReplies = () => (
  <div className="closed-replies">Replies are closed.</div>
);

const appOverrides = { DateSeparator: DayOnlySeparator };
const threadOverrides = { MessageComposerUI: ClosedReplies };

type ConversationProps = {
  channel: StreamChannel;
  thread?: StreamThread;
};

export const Conversation = ({ channel, thread }: ConversationProps) => (
  <WithComponents overrides={appOverrides}>
    <Channel channel={channel}>
      <ChannelHeader />
      <MessageList />
      <MessageComposer />
    </Channel>
    {thread && (
      <WithComponents overrides={threadOverrides}>
        <Thread thread={thread}>
          <ThreadHeader />
          <MessageList />
          <MessageComposer />
        </Thread>
      </WithComponents>
    )}
  </WithComponents>
);

Both message lists render DayOnlySeparator. Only the thread's composer renders ClosedReplies. The icons key merges icon by icon, so a nested WithComponents that sets one icon keeps the icons set above it.

Current override keys

"none" in the props column means the component receives no props: it reads what it needs from context. Where the default takes props of its own, the SDK still passes none: an override that renders the default can pass them. A default marked "built in" is a component the SDK doesn't export.

Key Replaces Props Default
AdditionalMessageComposerActions the area next to the composer's input that holds the emoji picker none AdditionalMessageComposerActions
Attachment a message's attachments AttachmentProps Attachment
AttachmentFileIcon the file-type icon on file attachments FileIconProps FileIcon
AttachmentPreviewList the attachment previews in the composer none; the default takes AttachmentPreviewListProps AttachmentPreviewList
AttachmentSelector the composer's attachment button and its menu none AttachmentSelector, and SimpleAttachmentSelector while editing a message
AttachmentSelectorInitiationButtonContents the content of the attachment button none the plus icon
AttachmentUploadProgressIndicator the progress of a message attachment that is still uploading AttachmentUploadProgressIndicatorProps AttachmentUploadProgressIndicator
AudioRecorder the voice recorder in the composer none AudioRecorder
AutocompleteSuggestionItem one item of the composer's suggestion list SuggestionItemProps SuggestionListItem
AutocompleteSuggestionList the composer's suggestion list SuggestionListProps SuggestionList
Avatar a user's avatar ChannelAvatarProps Avatar, and ChannelAvatar in channel-list rows, channel management and member details
AvatarStack a row of overlapping avatars AvatarStackProps AvatarStack
BaseImage an image, with its fallback when it fails to load BaseImageProps BaseImage
CalloutDialog the content of a callout dialog CalloutDialogProps built in
ChannelListHeader the channel list's header none ChannelListHeader
ChannelListItemActionButtons the action buttons of a channel-list row none ChannelListItemActionButtons
ChannelListItemUI a channel-list row ChannelListItemUIProps ChannelListItemUI
CommandChip the selected command in the composer CommandChipProps CommandChip
ContextMenu every context menu ContextMenuProps ContextMenu
ContextMenuContent a context menu's body and submenus ContextMenuContentProps ContextMenuContent
CooldownTimer the slow-mode countdown in the composer none CooldownTimer
DateSeparator the date separators in message lists DateSeparatorProps DateSeparator
EditedMessagePreview the preview of the message being edited, above the composer's input { message: LocalMessage; onCancel: () => void } built in
EmojiPicker the emoji picker button in the composer none none: register EmojiPicker from stream-chat-react/emojis
emojiSearchIndex the index the composer searches for emoji suggestions EmojiSearchIndex, not a component none
EmptyListIndicator what an empty channel list shows none an EmptyStateIndicator for channels
EmptyStateIndicator what an empty message list shows EmptyStateIndicatorProps EmptyStateIndicator
EndReachedIndicator the start or the end of a channel list { hasEnded: boolean; reached: "top" | "bottom" } renders nothing
extractDisplayInfo how a user becomes the name and image an avatar shows a function of { user }, not a component built in
FileSizeIndicator a file size label FileSizeIndicatorProps FileSizeIndicator
FirstPageLoadingIndicator a channel list loading its first page none LoadingChannels
Gallery the gallery's state and navigation GalleryProps Gallery
GalleryUI the gallery's slides and buttons none GalleryUI
GiphyPreviewMessage a Giphy preview below the messages of VirtualizedMessageList, with separateGiphyPreview GiphyPreviewMessageProps GiphyPreviewMessage
HeaderComponent content at the top of MessageList, or at its headerPosition none none
HeaderEndContent the end of the channel list's and the thread list's headers none none
icons the SDK's icons, merged icon by icon IconSlots, not a component the SDK's icons
ImagePlaceholder an image that failed to load ImagePlaceholderProps ImagePlaceholder
LinkPreviewList the link previews in the composer none LinkPreviewList
ListItem a row of a channel list { item: unknown } a ChannelListItem for the channel
LoadingIndicator the spinner of message lists, videos, the thread list and other parts LoadingIndicatorProps LoadingIndicator
LoadingNextPageIndicator a channel list loading its next page { isLoading?: boolean } a LoadingIndicator while loading
MessageActions a message's actions none MessageActions
MessageAlsoSentInChannelIndicator the "also sent in channel" mark on a reply none MessageAlsoSentInChannelIndicator
MessageBlocked a message blocked by moderation none MessageBlocked
MessageBouncePrompt the dialog for a bounced message MessageBouncePromptProps MessageBouncePrompt
MessageComposerUI the composer UI that MessageComposer renders none; the default takes MessageComposerProps MessageComposerUI
MessageDeleted a deleted message, in place of its bubble MessageDeletedProps none
MessageDeletedBubble the bubble of a deleted message none MessageDeletedBubble
MessageEditedIndicator the "Edited" mark none; the default takes MessageEditedIndicatorProps MessageEditedIndicator
MessageListItem the li around each item of MessageList PropsWithChildren li
MessageListMainPanel the panel around a message list and its notification list PropsWithChildren built in
MessageListWrapper the ul around the messages of MessageList PropsWithChildren ul
MessageReactions a message's reactions MessageReactionsProps MessageReactions
MessageReactionsDetail the dialog that lists who reacted MessageReactionsDetailProps MessageReactionsDetail
MessageRepliesCountButton the replies button on a message MessageRepliesCountButtonProps MessageRepliesCountButton
MessageStatus sending, sent, delivered or read none; the default takes MessageStatusProps MessageStatus
MessageSystem a system message EventComponentProps EventComponent
MessageTimestamp a message's timestamp and, when set, the time in the gallery header for media shared in a message MessageTimestampProps MessageTimestamp
MessageTranslationIndicator the "translated" mark TranslationIndicatorProps MessageTranslationIndicator
MessageUI a whole message, in both lists unless VirtualMessage is set none: read useMessageContext() MessageUI
Modal every modal ModalProps GlobalModal
ModalGallery a message's images, which open the gallery ModalGalleryProps ModalGallery
NewMessageNotification the "new messages" notification of a message list NewMessageNotificationProps, without label NewMessageNotification
Notification one notification in a NotificationList NotificationProps, with a ref Notification
NotificationAnnouncer the screen-reader announcements of notifications, rendered by Chat none; the default takes NotificationAnnouncerProps NotificationAnnouncer
NotificationList every notification list NotificationListProps NotificationList
PinIndicator the pinned mark PinIndicatorProps PinIndicator
PollActions a poll's buttons none PollActions
PollContent a poll in a message none PollContent
PollCreationDialog the dialog that creates a poll PollCreationDialogProps PollCreationDialog
PollHeader a poll's header none PollHeader
PollOptionSelector one option of a poll PollOptionSelectorProps PollOptionSelector
ProgressIndicator the progress of an upload, in composer previews, message attachments and the voice recorder ProgressIndicatorProps CircularProgressIndicator
QuotedMessage the quoted message inside a message none QuotedMessage
QuotedMessagePreview the quoted message above the composer's input none; the default takes QuotedMessagePreviewProps QuotedMessagePreview
reactionOptions the reactions users can pick ReactionOptions, not a component defaultReactionOptions
ReactionSelector the reaction picker ReactionSelectorProps, with a ref ReactionSelector
ReactionSelectorExtendedList the full reaction picker in the reactions dialog the props of ReactionSelector.ExtendedList ReactionSelector.ExtendedList
RecordingPermissionDeniedNotification the notice shown when microphone access is denied RecordingPermissionDeniedNotificationProps RecordingPermissionDeniedNotification
ReminderNotification a message's reminder mark ReminderNotificationProps ReminderNotification
Search the search UI none Search
SearchBar the search input none SearchBar
SearchResults the search results pane none SearchResults
SearchResultsHeader the header of the results pane none SearchResultsHeader
SearchResultsPresearch the results pane before the first search SearchResultsPresearchProps SearchResultsPresearch
SearchSourceResultList the result list of one search source none; the default takes SearchSourceResultListProps SearchSourceResultList
SearchSourceResultListFooter the end of one source's result list none SearchSourceResultListFooter
SearchSourceResults the section of one search source SearchSourceResultsProps: { searchSource } SearchSourceResults
SearchSourceResultsEmpty a source with no results none SearchSourceResultsEmpty
SearchSourceResultsHeader the header of one source's section none built in
SearchSourceResultsLoadingIndicator a source loading results none SearchSourceResultsLoadingIndicator
SendButton the send button SendButtonProps SendButton
SendToChannelCheckbox the "also send to channel" checkbox in a thread's composer none built in
ShareLocationDialog the location-sharing dialog ShareLocationDialogProps ShareLocationDialog
StartRecordingAudioButton the button that starts a voice recording StartRecordingAudioButtonProps StartRecordingAudioButton
StopAIGenerationButton the stop button while an AI response is generated ComponentProps<"button"> built in; null removes the button
StreamedMessageText the text of an AI-generated message StreamedMessageTextProps StreamedMessageText
SummarizedMessagePreview the latest-message preview of a channel-list row SummarizedMessagePreviewProps SummarizedMessagePreview
TextareaComposer the composer's text input none; the default takes TextareaComposerProps TextareaComposer
ThreadHead the parent message above a thread's replies MessageProps built in
ThreadListEmptyPlaceholder an empty thread list none built in
ThreadListItem a thread-list row ThreadListItemProps ThreadListItem
ThreadListItemUI the UI of a thread-list row ThreadListItemUIProps ThreadListItemUI
ThreadListLoadingIndicator a thread list loading none built in
ThreadListUnseenThreadsBanner the banner about threads with new replies none built in
ThreadStart the reply count under a thread's parent message none ThreadStart
Timestamp the date inside timestamps and the edited mark TimestampProps built in
TypingIndicator the typing indicator of message lists TypingIndicatorProps TypingIndicator in MessageList; none in VirtualizedMessageList
UnreadMessagesNotification the floating unread notification UnreadMessagesNotificationProps UnreadMessagesNotification
UnreadMessagesSeparator the unread separator UnreadMessagesSeparatorProps UnreadMessagesSeparator
UploadedSizeIndicator the uploaded and total size of an upload UploadedSizeIndicatorProps UploadedSizeIndicator
VideoPlayer video playback { controls?: boolean; isPlaying?: boolean; thumbnailUrl?: string; videoUrl?: string } built in
VirtualMessage a whole message, in VirtualizedMessageList only none: read useMessageContext() none: MessageUI renders
VoiceRecordingPreviewSlot the voice recording preview above the composer's attachments none; the default takes VoiceRecordingPreviewSlotProps VoiceRecordingPreviewSlot

The ComponentContextValue type also has FileDragAndDropContent and ScrollToLatestMessageButton. No component reads them, so setting them changes nothing.

Choosing between props and context

Use a key for a part the SDK renders, and a prop or your own children for a part you render yourself:

  • Components you render, such as ChannelHeader, ThreadHeader, MessageList and MessageComposer, have no key. Pass them props, or render something else in their place. ChannelHeader's StartContent, EndContent and Avatar are props for this reason; see Header content.
  • Parts the SDK renders, such as a message, the date separators or the notification list, have a key. Set it with WithComponents around the subtree that should use it.
  • Some components take a prop and read a key for the same part. The prop wins for that one instance. Gallery renders its GalleryUI prop, else the GalleryUI key, else the default. Attachment takes Image, Giphy, File and other props for the parts it renders, while the Attachment key replaces Attachment itself.

Channel and Thread render only their children, so their content is yours to compose. See Composition.

  • useComponentContext() returns the overrides in effect, or {} outside every provider.
  • useComponentContextIcons() returns every icon, with the icons overrides merged over the SDK's own. See Icons.