# Message UI components

> **Info:** This is release candidate documentation for **Stream Chat React Native SDK v10**. For the latest stable version, see the [latest version (v9)](https://getstream.io/chat/docs/sdk/react-native/).

The default [`MessageItemView`](https://getstream.io/chat/docs/sdk/react-native/v10/component-reference/message/message-ui/) is built from parts, and `stream-chat-react-native` exports them for a message view of your own. Each part reads the message from [`MessageContext`](https://getstream.io/chat/docs/sdk/react-native/v10/component-reference/message/messagecontext/), so most need no props inside a message. Each is an override key of the same name, except `MessageTextContainer`, whose text the `MessageText` key replaces.

## Best practices

- Compose these parts instead of rebuilding them. They handle states that are easy to miss, such as a message that is still sending, a failed message, an edited one or a reply sent to the channel.
- Replace one part through its override key, and keep the rest of the default view.
- Wrap the exported part when you only add to it, as the sample below does, so its own behavior stays.
- Change the actions in the message menu through `messageActions` on `Channel`, not through these parts. See [Message actions](https://getstream.io/chat/docs/sdk/react-native/v10/ui/customizing/actions/#message-actions).

## Basic usage

This replacement keeps the default status icon and adds "Read" once another member has read the message:

```tsx title="src/MessageStatusWithText.tsx"
import { StyleSheet, Text } from "react-native";
import {
  MessageStatus,
  type MessageStatusProps,
  useIsMessageReadByOthers,
  useMessageContext,
  WithComponents,
} from "stream-chat-react-native";

const MessageStatusWithText = (props: MessageStatusProps) => {
  const { message } = useMessageContext();
  const read = useIsMessageReadByOthers({ message });

  return (
    <>
      <MessageStatus {...props} />
      {read ? <Text style={styles.read}>Read</Text> : null}
    </>
  );
};

const overrides = { MessageStatus: MessageStatusWithText };

export const MessagesWithReadText = ({
  children,
}: {
  children: React.ReactNode;
}) => <WithComponents overrides={overrides}>{children}</WithComponents>;

const styles = StyleSheet.create({
  read: { fontSize: 12 },
});
```

[Status indicators](https://getstream.io/chat/docs/sdk/react-native/v10/ui-cookbook/message/status-indicators/) builds more of them.

## Available components

| Component                    | Renders                                                         | Exported                 |
| ---------------------------- | --------------------------------------------------------------- | ------------------------ |
| `MessageAuthor`              | the sender's avatar, or a spacer of the same width              | yes                      |
| `MessageHeader`              | the reminder, pinned and sent-to-channel marks above the bubble | yes                      |
| `MessagePinnedHeader`        | "Pinned by" and the name, or "You"                              | yes                      |
| `MessageReminderHeader`      | "Reminder set" or "Reminder overdue", with the time left        | yes                      |
| `MessageSavedForLaterHeader` | "Saved For Later"                                               | yes                      |
| `SentToChannelHeader`        | "Also sent in channel" or "Replied to a thread", with **View**  | yes                      |
| `MessageTextContainer`       | the message's text, as Markdown                                 | yes, not an override key |
| `MessageFooter`              | the sender's name, the status, the time and "Edited"            | yes                      |
| `MessageTimestamp`           | the time                                                        | yes                      |
| `MessageStatus`              | the delivery status icon of the user's own messages             | yes                      |
| `MessageReplies`             | the replies button, with the participants' avatars              | yes                      |
| `MessageRepliesAvatars`      | the avatars of up to three thread participants                  | yes                      |
| `MessageDeleted`             | "Message deleted" and the footer                                | yes                      |
| `MessageError`               | the error badge on a failed or error message                    | yes                      |
| `MessageBlocked`             | a message blocked by moderation, in place of the message view   | yes                      |
| `MessageBounce`              | the dialog of a bounced message                                 | yes                      |
| `MessageSystem`              | a system message, in place of `Message`                         | yes                      |
| `StreamingMessageView`       | the text of an AI-generated message, revealed as it streams     | yes                      |

## MessageAuthor

Renders the sender's avatar on messages aligned left. Where the avatar doesn't show, it renders an empty view of the same size, so the bubbles of a group stay aligned. It re-renders only when `lastGroupMessage` or the sender's ID, name or image changes.

| Prop               | Type                                            | Default               | Description                                    |
| ------------------ | ----------------------------------------------- | --------------------- | ---------------------------------------------- |
| `lastGroupMessage` | `boolean`                                       | from `MessageContext` | Shows the avatar when `showAvatar` isn't set.  |
| `message`          | `LocalMessage`                                  | from `MessageContext` | The message whose sender is shown.             |
| `showAvatar`       | `boolean`                                       | from `MessageContext` | Shows or hides the avatar, whatever the group. |
| `size`             | `"sm" \| "md" \| "lg" \| "xl" \| "xs" \| "2xl"` | `'md'`                | The avatar's size.                             |

## MessageHeader

Renders, above the bubble, the `MessageReminderHeader` override when the message has a reminder with a time, or the `MessageSavedForLaterHeader` override when it has one without; the `MessagePinnedHeader` override for a pinned message; and the `SentToChannelHeader` override for a reply also sent to the channel. It renders nothing when none applies. It reads the message and its reminder from context.

| Prop      | Type           | Default               | Description                                                                                      |
| --------- | -------------- | --------------------- | ------------------------------------------------------------------------------------------------ |
| `message` | `LocalMessage` | from `MessageContext` | Passed to `MessagePinnedHeader`. Which marks show still follows the message in `MessageContext`. |

### MessagePinnedHeader

Renders "Pinned by" and the name of who pinned the message, or "You". It renders nothing for a message that isn't pinned.

| Prop      | Type           | Default               | Description  |
| --------- | -------------- | --------------------- | ------------ |
| `message` | `LocalMessage` | from `MessageContext` | The message. |

### MessageReminderHeader

Renders "Reminder set" and the time left, from the `duration.messageReminder` translation key, or "Reminder overdue". It reads the reminder of the message in `MessageContext`.

| Prop                 | Type      | Default                              | Description                                   |
| -------------------- | --------- | ------------------------------------ | --------------------------------------------- |
| `isReminderTimeLeft` | `boolean` | `true` while `timeLeftMs` is above 0 | Picks "Reminder set" over "Reminder overdue". |
| `timeLeftMs`         | `number`  | the reminder's `timeLeftMs`          | The time until the reminder, in milliseconds. |

### MessageSavedForLaterHeader

Renders "Saved For Later" with a bookmark icon. It takes no props. The exported `MessageSavedForLaterHeaderProps` type lists `message`, which the component doesn't read.

### SentToChannelHeader

Renders "Also sent in channel" on a reply shown in a thread, and "Replied to a thread" on the same reply shown in the channel. With `onAlsoSentToChannelHeaderPress` set on `Channel` or `Thread`, it adds **View**: in a thread, pressing it calls the handler with the message's ID; in a channel, with the message's ID and the reply's `Thread`, loading the parent message first when it isn't loaded.

| Prop           | Type         | Default                                                   | Description                                             |
| -------------- | ------------ | --------------------------------------------------------- | ------------------------------------------------------- |
| `onPress`      | `() => void` | calls `onAlsoSentToChannelHeaderPress` as described above | Called when the user presses **View**.                  |
| `showViewText` | `boolean`    | `true` when `onAlsoSentToChannelHeaderPress` is set       | Shows **View**.                                         |
| `thread`       | `Thread`     | from `ThreadContext`                                      | Picks the text: "Also sent in channel" inside a thread. |

## MessageTextContainer

Renders the message's text as Markdown, with mentions and links that can be pressed. When the message has an auto-translation into the user's language, it renders that instead. It renders nothing for a message without text. With the `MessageText` override set, it renders that inside its container instead, with its own props, `renderText` (the exported function it renders with by default) and `theme`; see [Overriding components](https://getstream.io/chat/docs/sdk/react-native/v10/ui/customizing/overriding-components/#optional-slots).

| Prop                                 | Type                                                | Default                | Description                                                                                           |
| ------------------------------------ | --------------------------------------------------- | ---------------------- | ----------------------------------------------------------------------------------------------------- |
| `hasInteractiveAccessibilityContent` | `boolean`                                           | from `MessageContext`  | Makes the text its own accessibility element.                                                         |
| `isMyMessage`                        | `boolean`                                           | from `MessageContext`  | Picks the colors of the user's own messages.                                                          |
| `markdownRules`                      | `MarkdownRules`                                     | from `MessagesContext` | `simple-markdown` rules merged over the SDK's.                                                        |
| `markdownStyles`                     | `MarkdownStyle`                                     |                        | Styles merged over `theme.messageItemView.content.markdown`.                                          |
| `message`                            | `LocalMessage`                                      | from `MessageContext`  | The message whose text renders.                                                                       |
| `messageOverlay`                     | `boolean`                                           |                        | Set when the text renders in the message menu. The text then re-renders when `markdownStyles` change. |
| `messageTextNumberOfLines`           | `number`                                            | from `MessagesContext` | Truncates the text to this many lines, and renders only the first paragraph.                          |
| `myMessageTheme`                     | `DeepPartial<Theme>`                                | from `MessagesContext` | The text re-renders when it changes.                                                                  |
| `onLongPress`                        | `(payload: PressableHandlerPayload) => void`        | from `MessageContext`  | Called on a long press on the text.                                                                   |
| `onlyEmojis`                         | `boolean`                                           | from `MessageContext`  | Applies the `onlyEmojiMarkdown` style.                                                                |
| `onPress`                            | `(payload: MessagePressableHandlerPayload) => void` | from `MessageContext`  | Called on a press on a link or a mention, with the `textLink` or `textMention` emitter.               |
| `preventPress`                       | `boolean`                                           | from `MessageContext`  | Turns off presses on the text.                                                                        |
| `styles`                             | `Partial<{ textContainer: StyleProp<ViewStyle>; }>` |                        | Style of the view around the text.                                                                    |

## MessageFooter

Renders, under the bubble, the sender's name on other users' messages, except in a channel with exactly two members, the `MessageStatus` override when `showMessageStatus` is set, the `MessageTimestamp` override, and "Edited" on an edited message that isn't AI-generated. It renders nothing for a message the server accepted that isn't the last of its group.

| Prop                | Type             | Default               | Description                                                                                                         |
| ------------------- | ---------------- | --------------------- | ------------------------------------------------------------------------------------------------------------------- |
| `alignment`         | `Alignment`      | from `MessageContext` | The sender's name shows on `'left'` messages only.                                                                  |
| `date`              | `string \| Date` |                       | The time to show, passed to `MessageTimestamp` as `timestamp`. `MessageItemView` passes the message's `created_at`. |
| `formattedDate`     | `string \| Date` |                       | Text shown in place of the formatted `date`.                                                                        |
| `lastGroupMessage`  | `boolean`        | from `MessageContext` | With `false`, the footer shows only on a message that is sending or failed.                                         |
| `message`           | `LocalMessage`   | from `MessageContext` | The message.                                                                                                        |
| `otherAttachments`  | `Attachment[]`   |                       | Not used.                                                                                                           |
| `showMessageStatus` | `boolean`        | from `MessageContext` | Shows `MessageStatus`.                                                                                              |

## MessageTimestamp

Renders a time formatted with a translation key. It renders nothing when there's no time to show.

| Prop                      | Type              | Default                        | Description                                                                                                                                                           |
| ------------------------- | ----------------- | ------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `formattedDate`           | `string \| Date`  |                                | Text shown as is, in place of the formatted `timestamp`.                                                                                                              |
| `tDateTimeParser`         | `TDateTimeParser` | from `TranslationContext`      | Parses the time for formatting.                                                                                                                                       |
| `timestamp`               | `string \| Date`  |                                | The time to format.                                                                                                                                                   |
| `timestampTranslationKey` | `string`          | `'timestamp.MessageTimestamp'` | The translation key whose value is the format. See [Date and time formatting](https://getstream.io/chat/docs/sdk/react-native/v10/ui/customizing/localization/#date-and-time-formatting). |

## MessageStatus

Renders the status of one of the user's own messages: a clock while sending, one check once the server accepted it, and two checks once it reached or was read by another member, in a different color when read. It renders nothing for a failed or error message. [Read state, unread and receipts](https://getstream.io/chat/docs/sdk/react-native/v10/features/messaging/read-state-unread-and-receipts/) explains where the receipts come from.

| Prop        | Type           | Default                                      | Description                                            |
| ----------- | -------------- | -------------------------------------------- | ------------------------------------------------------ |
| `delivered` | `boolean`      | `useIsMessageDeliveredToOthers({ message })` | Whether the message reached at least one other member. |
| `message`   | `LocalMessage` | from `MessageContext`                        | The message.                                           |
| `read`      | `boolean`      | `useIsMessageReadByOthers({ message })`      | Whether at least one other member read the message.    |

## MessageReplies

Renders "1 Reply" or "5 Replies", the `MessageRepliesAvatars` override and a connector line. It renders nothing for a message without replies. Pressing it reports the `messageReplies` emitter with `onOpenThread` as the default handler, so it calls the list's `onThreadSelect`. `MessageItemView` doesn't render it inside a thread; a view of your own that renders it checks `useThreadContext().thread` itself.

| Prop           | Type                                                   | Default                   | Description                                  |
| -------------- | ------------------------------------------------------ | ------------------------- | -------------------------------------------- |
| `alignment`    | `Alignment`                                            | from `MessageContext`     | Puts the connector on the left or the right. |
| `isMyMessage`  | `boolean`                                              | from `MessageContext`     | Picks the connector's color.                 |
| `message`      | `LocalMessage`                                         | from `MessageContext`     | The message whose `reply_count` shows.       |
| `onLongPress`  | `(payload: PressableHandlerPayload) => void`           | from `MessageContext`     | Called on a long press.                      |
| `onOpenThread` | `() => void`                                           | from `MessageContext`     | The default handler of a press.              |
| `onPress`      | `(payload: MessagePressableHandlerPayload) => void`    | from `MessageContext`     | Called on a press.                           |
| `onPressIn`    | `((payload: PressableHandlerPayload) => void) \| null` | from `MessageContext`     | Called when a press starts.                  |
| `preventPress` | `boolean`                                              | from `MessageContext`     | Turns off presses.                           |
| `t`            | `StreamTFunction`                                      | from `TranslationContext` | Translates the label.                        |

### MessageRepliesAvatars

Renders the avatars of up to three of the message's `thread_participants`.

| Prop      | Type           | Default               | Description                          |
| --------- | -------------- | --------------------- | ------------------------------------ |
| `message` | `LocalMessage` | from `MessageContext` | The message whose participants show. |

## MessageDeleted

Renders "Message deleted" in a bubble, and the `MessageFooter` override under it. `MessageItemView` renders it in place of the headers, the bubble, the reactions and the replies of a deleted message.

| Prop         | Type             | Default               | Description                                                                                                                                        |
| ------------ | ---------------- | --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
| `alignment`  | `Alignment`      | from `MessageContext` | Aligns the bubble left or right.                                                                                                                   |
| `date`       | `string \| Date` |                       | Passed to `MessageFooter`.                                                                                                                         |
| `groupStyle` | `string`         | required              | The alignment and group, such as `'left_bottom'`. `left_bottom`, `left_single`, `right_bottom` and `right_single` give the bubble its tail corner. |
| `message`    | `LocalMessage`   | from `MessageContext` | The component re-renders when its type, text, status, reply count or pinned state changes.                                                         |

## MessageError

Renders the error badge at the top corner of a failed or error message's bubble. It takes no props.

## MessageBlocked

Renders the text of a message that moderation blocked, centered in a pill. `Message` renders it in place of the message view.

| Prop      | Type                   | Default  | Description                               |
| --------- | ---------------------- | -------- | ----------------------------------------- |
| `message` | `LocalMessage`         | required | The blocked message. Its `text` is shown. |
| `style`   | `StyleProp<ViewStyle>` |          | Style of the container.                   |

## MessageBounce

Shows the dialog of a message that moderation bounced: "Send Anyway" resends it, "Edit Message" puts it in the composer, and "Delete Message" removes it from the list. It renders no view of its own, and opens a native alert when it renders. `Message` renders it when the user presses or long presses a bounced message.

| Prop                    | Type                                                              | Default                          | Description                                           |
| ----------------------- | ----------------------------------------------------------------- | -------------------------------- | ----------------------------------------------------- |
| `message`               | `LocalMessage`                                                    | from `MessageContext`            | The bounced message.                                  |
| `removeMessage`         | `(message: { id: string; parent_id?: string; }) => Promise<void>` | from `useMessageOperations()`    | Removes the message locally, for "Delete Message".    |
| `retrySendMessage`      | `(message: LocalMessage) => Promise<void>`                        | from `useMessageOperations()`    | Resends the message, for "Send Anyway".               |
| `setEditingState`       | `(message?: LocalMessage) => void`                                | from `MessageComposerAPIContext` | Puts the message in the composer, for "Edit Message". |
| `setIsBounceDialogOpen` | `React.Dispatch<React.SetStateAction<boolean>>`                   | required                         | Closes the dialog. Each button calls it with `false`. |

[Replacing the bounce alert](https://getstream.io/chat/docs/sdk/react-native/v10/features/messaging/sending-editing-and-deleting/#replacing-the-bounce-alert) shows a replacement.

## MessageSystem

Renders a system message, such as "Cleo joined the channel", with its time from the `timestamp.MessageSystem` translation key. The list renders it in place of `Message` for a message of type `system`.

| Prop      | Type                   | Default  | Description                                                                   |
| --------- | ---------------------- | -------- | ----------------------------------------------------------------------------- |
| `message` | `LocalMessage`         | required | The system message.                                                           |
| `style`   | `StyleProp<ViewStyle>` |          | Style of the container. The list passes `theme.messageList.messageContainer`. |

## StreamingMessageView

Renders the text of an AI-generated message with `MessageTextContainer`, revealing new text a few letters at a time as the message updates. The text the message had when it mounted shows at once. `MessageContent` renders it in place of the text when `isMessageAIGenerated` on `Chat` returns `true` for the message. [StreamingMessageView](https://getstream.io/chat/docs/sdk/react-native/v10/features/ai/sdk-integration/#streamingmessageview) covers the AI setup.

| Prop                   | Type           | Default               | Description                                  |
| ---------------------- | -------------- | --------------------- | -------------------------------------------- |
| `letterInterval`       | `number`       | `0`                   | The delay between steps, in milliseconds.    |
| `message`              | `LocalMessage` | from `MessageContext` | The message whose text streams.              |
| `renderingLetterCount` | `number`       | `2`                   | The number of letters revealed at each step. |

## Related hooks

- `useMessageContext()` reads the message the parts render.
- `useIsMessageReadByOthers({ message })` and `useIsMessageDeliveredToOthers({ message })` give the receipts `MessageStatus` shows, and `useMessageReadData` and `useMessageDeliveredData` who read the message and who received it. See [Message hooks](https://getstream.io/chat/docs/sdk/react-native/v10/reference/hooks/message-hooks/).
- `useMessageReminder(messageId)` returns the reminder `MessageHeader` reads.
- `useStreamingMessage({ text })` reveals text the way `StreamingMessageView` does.

---

For the most recent version of this documentation, visit [https://getstream.io/chat/docs/sdk/react-native/v10/component-reference/message/message-ui-components/](https://getstream.io/chat/docs/sdk/react-native/v10/component-reference/message/message-ui-components/).