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

ComponentContext

ComponentContext holds the React Chat SDK UI override surface for a Channel subtree. Read it with useComponentContext(). Register overrides with WithComponents.

Best Practices

  • Scope overrides with WithComponents as close as possible to the subtree that needs them.
  • Prefer wrapping or lightly extending default SDK components before replacing whole surfaces.
  • Keep custom message UIs based on useMessageContext() and related hooks, not on assumed injected props.
  • Use local component props only when that component still exposes a supported prop surface.
  • Keep your override map documented, because most SDK UI customization now flows through ComponentContext.

Basic Usage

Read values from the context inside any Channel child:

import { useComponentContext } from "stream-chat-react";

export const CustomMessageListHeader = () => {
  const { EmptyStateIndicator, MessageActions } = useComponentContext();
  return (
    <div>
      <span>
        {EmptyStateIndicator ? "empty state available" : "no override"}
      </span>
      <span>
        {MessageActions ? "custom actions registered" : "default actions"}
      </span>
    </div>
  );
};

Registering Overrides With WithComponents

WithComponents merges the nearest override set into the existing ComponentContext. Inner wrappers win over outer wrappers.

import {
  Channel,
  ChannelHeader,
  MessageInput,
  MessageList,
  Thread,
  Window,
  WithComponents,
} from "stream-chat-react";

export const App = () => {
  return (
    <WithComponents
      overrides={{
        Input: CustomMessageInput,
        Message: CustomMessage,
        MessageActions: CustomMessageActions,
      }}
    >
      <Channel>
        <Window>
          <ChannelHeader />
          <MessageList />
          <MessageInput />
        </Window>
        <Thread />
      </Channel>
    </WithComponents>
  );
};

You can scope overrides more narrowly too:

import {
  Channel,
  MessageInput,
  MessageList,
  Thread,
  Window,
  WithComponents,
} from "stream-chat-react";

export const App = () => {
  return (
    <WithComponents overrides={{ Input: MainChannelInput }}>
      <Channel>
        <Window>
          <MessageList />
          <MessageInput />
        </Window>
        <WithComponents overrides={{ Input: ThreadInputOverride }}>
          <Thread />
        </WithComponents>
      </Channel>
    </WithComponents>
  );
};

Message and VirtualMessage overrides should read SDK state from hooks like useMessageContext() instead of assuming the SDK injects message UI props directly.

Current Override Keys

The current ComponentContext value includes the following keys.

Composer And Input

KeyUse for
AdditionalMessageComposerActionsextra composer action buttons next to the textarea
AttachmentPreviewListthe shared preview list in MessageInput
AttachmentSelectorthe attachment selector UI
AttachmentSelectorInitiationButtonContentsthe selector button contents
AudioRecorderthe voice-recording composer surface
AutocompleteSuggestionItemindividual suggestion-list items
AutocompleteSuggestionListthe suggestion-list container
CommandChipthe selected command chip
CooldownTimerthe slow-mode cooldown UI
EditedMessagePreviewthe edit-preview row shown by the composer
EmojiPickerthe emoji picker trigger and picker UI
FileDragAndDropContentthe drag-and-drop overlay content
ImagePlaceholderthe failed-image placeholder UI
Inputthe high-level message input UI
LinkPreviewListlink previews inside the composer preview stack
RecordingPermissionDeniedNotificationthe recorder permission-denied UI
SendButtonthe send button
SendToChannelCheckboxthe thread reply "also send to channel" checkbox
ShareLocationDialogthe location-sharing dialog UI
StartRecordingAudioButtonthe audio-recording start button
StopAIGenerationButtonthe AI generation stop button in composer actions
TextareaComposerthe text input control
VoiceRecordingPreviewSlotthe dedicated voice-recording preview slot above attachments
emojiSearchIndexcustom emoji search implementation for the composer

Message, Notifications, And Lists

KeyUse for
Attachmentmessage attachment rendering
DateSeparatordate separators in message lists
EmptyStateIndicatorempty list or empty thread placeholders
GiphyPreviewMessagegiphy preview rows in message lists
HeaderComponentcontent rendered above MessageList
LoadingErrorIndicatorloading error UI
LoadingIndicatorloading UI while querying or paginating
Messagethe default non-virtualized message renderer
MessageActionsthe message actions surface
MessageAlsoSentInChannelIndicatorthe thread "also sent in channel" indicator
MessageBlockedmoderation-blocked message UI
MessageBouncePromptbounced message prompt content
MessageDeletedalternate deleted-message renderer with no default
MessageDeletedBubbledeleted message bubble renderer
MessageEditedIndicatorCustom UI component to display the "Edited" label and tooltip when a message has been edited
MessageListItemwrapper for each list item
MessageListMainPanelthe main panel around the message list
MessageListNotificationsmessage-list notifications container
MessageListWrapperwrapper around the list contents
MessageRepliesCountButtonreplies-count button
MessageReactionsDetailreaction detail dialog content
MessageStatusmessage delivery and read status
MessageSystemsystem message rendering
MessageTimestampper-message timestamp UI
MessageTranslationIndicatortranslation indicator UI
NewMessageNotificationthe "new messages" notification
NotificationListthe client-notification list UI
PinIndicatorpinned-message indicator
QuotedMessagequoted message rendering in message bubbles
ReminderNotificationreminder UI in messages
StreamedMessageTextstreamed AI text rendering
TypingIndicatorthe message-list typing indicator
UnreadMessagesNotificationthe unread notification while scrolled away
UnreadMessagesSeparatorthe unread separator row
VirtualMessagethe virtualized message renderer

Reactions, Polls, And Media

KeyUse for
Avatarsingle-user avatar rendering
AvatarStackstacked avatar rendering
BaseImagelow-level image rendering and fallbacks
Gallerygallery carousel UI
Modalthe modal shell used by SDK features
ModalGallerygallery viewer content
PollActionspoll actions renderer
PollContentpoll body renderer
PollCreationDialogpoll creation dialog contents
PollHeaderpoll header renderer
PollOptionSelectorpoll option selector UI
QuotedMessagePreviewquoted-message preview inside the composer
ReactionSelectorthe reaction selector UI
ReactionsListthe inline reactions list
VideoPlayervideo playback UI
reactionOptionsshared reaction options for selector and list components

Channel Preview, Thread, Search, And Shared Utility UI

KeyUse for
CalloutDialogcallout-dialog contents
ChannelPreviewActionButtonsaction buttons inside ChannelPreviewMessenger
Searchthe main search UI
SearchBarthe search input area
SearchResultsthe results pane
SearchResultsHeaderresults header content
SearchResultsPresearchthe pre-query state for results
SearchSourceResultListthe result-list UI for one source
SearchSourceResultListFooterend-of-list footer for one source
SearchSourceResultsone source section in search results
SearchSourceResultsEmptyempty state for one source
SearchSourceResultsHeaderheader for one source section
SearchSourceResultsLoadingIndicatorloading state for one source section
ThreadHeadthread parent/header message at the top of thread lists
ThreadHeaderthread header UI
ThreadInputthread message input UI
ThreadListEmptyPlaceholderempty state in thread lists
ThreadListItemthread list item wrapper
ThreadListItemUIthread list item UI
ThreadListLoadingIndicatorthread list loading UI
ThreadListUnseenThreadsBannerunseen-thread banner
ThreadStartthread-start marker or content
Timestampshared timestamp component used by other UI

Choosing Between Props And Context

Use the local component prop when that component still exposes a supported prop surface. Use WithComponents and ComponentContext when you want to replace SDK-owned UI deeper in the tree.

Examples:

  • use <MessageInput Input={CustomInput} /> when customizing one specific MessageInput instance
  • use <WithComponents overrides={{ Input: CustomInput }}> when you want every nested SDK input to use the same override
  • use <WithComponents overrides={{ MessageActions: CustomMessageActions }}> when you want to replace the default message action UI