const CustomMessage = () => {
// consume `MessageContext` and render custom component here
};
<Chat client={client}>
<Channel channel={channel} Message={CustomMessage}>
<MessageList />
<MessageInput />
</Channel>
</Chat>;Message UI
The Message UI component consumes MessageContext and renders a message. It’s typically composed of smaller subcomponents (text, reactions, etc.) that also consume MessageContext.
Each message list uses a default Message UI component. If you don’t supply one, MessageSimple is used.
Best Practices
- Start by composing existing subcomponents instead of building from scratch.
- Use
useMessageContextin custom UI to avoid prop-drilling. - Keep option buttons consistent between channel and thread UIs.
- Prefer list-level overrides (
MessageList/Thread) over global defaults when scoped. - Reuse
MessageSimplestructure as a baseline for accessibility and layout.
Basic Usage
Example 1 - Add Message UI component to MessageList.
To use your own Message UI in MessageList, pass Message to Channel, MessageList, or Thread. Channel sets a default in ComponentContext, while MessageList/Thread override that value. If both are set, the list-level prop wins.
Example 2 - Add Message UI component to VirtualizedMessageList.
For VirtualizedMessageList, pass VirtualMessage on Channel or Message on VirtualizedMessageList. Channel sets a default in context, and the list-level prop overrides it. FixedHeightMessage is still available but is no longer the default.
const CustomMessage = () => {
// consume `MessageContext` and render custom component here
};
<Chat client={client}>
<Channel channel={channel} VirtualMessage={CustomMessage}>
<VirtualizedMessageList />
<MessageInput />
</Channel>
</Chat>;UI Customization
MessageSimple and FixedHeightMessage are meant as guides. They compose smaller UI pieces that each handle a specific part of message rendering.
If we strip MessageSimple down to its core pieces, the component resembles the following snippet:
<div>
<MessageStatus />
<Avatar />
<div>
<MessageOptions />
<div>
<ReactionsList />
<ReactionSelector />
</div>
<div>
<Attachment />
<MessageText />
<MessageErrorIcon />
</div>
</div>
<MessageRepliesCountButton />
<div>
<MessageTimestamp />
</div>
</div>We recommend following a similar pattern: mix and match the exported subcomponents to suit your layout. Each subcomponent reads from MessageContext and requires little or no props.
For a detailed example, review the Message UI Customization example.
Message options
The default Message UI renders three option buttons next to the message content:
- button to open message actions drop-down menu - message actions box
- button to open thread
- button to open reaction selector
In a thread, the “open thread” button is omitted.
Message actions box
The menu contains default actions based on user permissions. You can also add custom actions, which appear as extra menu items.
Props
All Message UI props override values from MessageContext. For custom components, prefer useMessageContext. If you build on MessageSimple, you can override individual props as needed.
actionsEnabled
If true, actions such as edit, delete, flag, etc. are enabled on the message (overrides the value stored in MessageContext).
| Type | Default |
|---|---|
| boolean | true |
additionalMessageInputProps
Additional props to be passed to the underlying MessageInput component that's rendered
while editing (overrides the value stored in MessageContext).
| Type |
|---|
| object |
autoscrollToBottom
Call this function to keep the list pinned to the bottom when its scroll height increases (only in VirtualizedMessageList). It won’t auto-scroll if the user is more than 4px away from the bottom.
You can even use the function to keep the container scrolled to the bottom while images are loading:
const Image = (props: ImageProps) => {
...
const { autoscrollToBottom } = useMessageContext();
...
return (
<img
...
onLoad={autoscrollToBottom}
...
/>
);
};| Type |
|---|
| () => void |
clearEditingState
When called, this function will exit the editing state on the message (overrides the function stored in MessageContext).
| Type |
|---|
| (event?: React.BaseSyntheticEvent) => void |
customMessageActions
An object containing custom message actions (key) and function handlers (value) (overrides the value stored in MessageContext). The key is used as a display text inside the button. Therefore, it should not be cryptic but rather bear the end user in mind when formulating it.
const customActions = {
"Copy text": (message) => {
navigator.clipboard.writeText(message.text || "");
},
};
<MessageList customMessageActions={customActions} />;Custom action item "Copy text" in the message actions box:

| Type |
|---|
| object |
deliveredTo
An array of user IDs that have confirmed the message delivery to their device.
| Type |
|---|
UserResponse[] |
editing
If true, the message toggles to an editing state (overrides the value stored in MessageContext).
| Type | Default |
|---|---|
| boolean | false |
formatDate
Overrides the default date formatting logic, has access to the original date object (overrides the function stored in MessageContext).
| Type |
|---|
| (date: Date) => string |
getMessageActions
Function that returns an array of the allowed actions on a message by the currently connected user (overrides the function stored in MessageContext).
| Type |
|---|
| () => MessageActionsArray |
groupByUser
If true, group messages sent by each user (only used in the VirtualizedMessageList).
| Type | Default |
|---|---|
| boolean | false |
groupStyles
An array of potential styles to apply to a grouped message (ex: top, bottom, single) (overrides the value stored in MessageContext).
| Type | Options |
|---|---|
| string[] | '' | 'middle' | 'top' | 'bottom' | 'single' |
handleAction
Function that calls an action on a message (overrides the function stored in MessageContext).
| Type | Default |
|---|---|
| (dataOrName?: string | FormData, value?: string, event?: React.BaseSyntheticEvent) => Promise<void> | MessageContextValue['handleAction'] |
handleDelete
Function that removes a message from the current channel (overrides the function stored in MessageContext).
| Type | Default |
|---|---|
| (event: React.BaseSyntheticEvent, options?: DeleteMessageOptions) => Promise<void> | void | MessageContextValue['handleDelete'] |
handleEdit
Function that edits a message (overrides the function stored in MessageContext).
| Type | Default |
|---|---|
| (event: React.BaseSyntheticEvent) => Promise<void> | void | MessageContextValue['handleEdit'] |
handleFetchReactions
Function that loads the reactions for a message (overrides the function stored in MessageContext).
| Type | Default |
|---|---|
| (event: React.BaseSyntheticEvent) => Promise<void> | void | MessageContextValue['handleFetchReactions'] |
This function limits the number of loaded reactions to 1200. To customize this behavior, you can pass a custom ReactionsList component.
handleFlag
Function that flags a message (overrides the function stored in MessageContext).
| Type | Default |
|---|---|
| (event: React.BaseSyntheticEvent) => Promise<void> | void | MessageContextValue['handleFlag'] |
handleMarkUnread
Function that marks the message and all the following messages as unread in a channel. (overrides the function stored in MessageContext).
| Type | Default |
|---|---|
| (event: React.BaseSyntheticEvent) => Promise<void> | void | MessageContextValue['handleMarkUnread'] |
handleMute
Function that mutes the sender of a message (overrides the function stored in MessageContext).
| Type | Default |
|---|---|
| (event: React.BaseSyntheticEvent) => Promise<void> | void | MessageContextValue['handleMute'] |
handleOpenThread
Function that opens a Thread on a message (overrides the function stored in MessageContext).
| Type | Default |
|---|---|
| (event: React.BaseSyntheticEvent) => Promise<void> | void | MessageContextValue['handleOpenThread'] |
handlePin
Function that pins a message in the current channel (overrides the function stored in MessageContext).
| Type | Default |
|---|---|
| (event: React.BaseSyntheticEvent) => Promise<void> | void | MessageContextValue['handlePin'] |
handleReaction
Function that adds a reaction on a message (overrides the function stored in MessageContext).
| Type | Default |
|---|---|
| (event: React.BaseSyntheticEvent) => Promise<void> | void | MessageContextValue['handleReaction'] |
handleRetry
Function that retries sending a message after a failed request (overrides the function stored in ChannelActionContext).
| Type | Default |
|---|---|
| (message: LocalMessage) => Promise<void> | ChannelActionContextValue['retrySendMessage'] |
initialMessage
When true, signifies the message is the parent message in a thread list (overrides the value stored in MessageContext).
| Type | Default |
|---|---|
| boolean | false |
isMyMessage
Function that returns whether a message belongs to the current user (overrides the function stored in MessageContext).
| Type |
|---|
| () => boolean |
isReactionEnabled (deprecated)
If true, sending reactions is enabled in the currently active channel (overrides the value stored in MessageContext).
| Type | Default |
|---|---|
| boolean | true |
lastReceivedId
The latest message ID in the current channel (overrides the value stored in MessageContext).
| Type |
|---|
| string |
message
The StreamChat message object, which provides necessary data to the underlying UI components (overrides the value stored in MessageContext).
| Type |
|---|
| object |
messageListRect
DOMRect object linked to the parent MessageList component (overrides the value stored in MessageContext).
| Type |
|---|
| DOMRect |
mutes
An array of users that have been muted by the connected user (overrides the value stored in MessageContext).
| Type | Default |
|---|---|
| Mute[] | ChannelStateContext['mutes'] |
onMentionsClickMessage
Function that runs on click of an @mention in a message (overrides the function stored in MessageContext).
| Type | Default |
|---|---|
| (event: React.BaseSyntheticEvent) => Promise<void> | void | MessageContextValue['onMentionsClickMessage'] |
onMentionsHoverMessage
Function that runs on hover of an @mention in a message (overrides the function stored in MessageContext).
| Type | Default |
|---|---|
| (event: React.BaseSyntheticEvent) => Promise<void> | void | MessageContextValue['onMentionsHoverMessage'] |
onUserClick
Function that runs on click of a user avatar (overrides the function stored in MessageContext).
| Type | Default |
|---|---|
| (event: React.BaseSyntheticEvent) => Promise<void> | void | MessageContextValue['onUserClick'] |
onUserHover
Function that runs on hover of a user avatar (overrides the function stored in MessageContext).
| Type | Default |
|---|---|
| (event: React.BaseSyntheticEvent) => Promise<void> | void | MessageContextValue['onUserHover'] |
pinPermissions
The user roles allowed to pin messages in various channel types (deprecated in favor of channelCapabilities).
| Type | Default |
|---|---|
| object | defaultPinPermissions |
readBy
An array of users that have read the current message (overrides the value stored in MessageContext).
| Type |
|---|
| array |
renderText
Custom function to render message text content (overrides the function stored in MessageContext).
| Type | Default |
|---|---|
| function | renderText |
setEditingState
Function to toggle the editing state on a message (overrides the function stored in MessageContext).
| Type |
|---|
| (event: React.BaseSyntheticEvent) => Promise<void> | void |
threadList
If true, indicates that the current MessageList component is part of a Thread (overrides the value stored in MessageContext).
| Type | Default |
|---|---|
| boolean | false |
unsafeHTML
If true, renders HTML instead of markdown. Posting HTML is only supported server-side (overrides the value stored in MessageContext).
| Type | Default |
|---|---|
| boolean | false |
- Best Practices
- Basic Usage
- UI Customization
- Props
- actionsEnabled
- additionalMessageInputProps
- autoscrollToBottom
- clearEditingState
- customMessageActions
- deliveredTo
- editing
- formatDate
- getMessageActions
- groupByUser
- groupStyles
- handleAction
- handleDelete
- handleEdit
- handleFetchReactions
- handleFlag
- handleMarkUnread
- handleMute
- handleOpenThread
- handlePin
- handleReaction
- handleRetry
- initialMessage
- isMyMessage
- isReactionEnabled (deprecated)
- lastReceivedId
- message
- messageListRect
- mutes
- onMentionsClickMessage
- onMentionsHoverMessage
- onUserClick
- onUserHover
- pinPermissions
- readBy
- renderText
- setEditingState
- threadList
- unsafeHTML