# MessageComposer

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

`MessageComposer` renders the message input of a channel or a thread. The message being written lives in a `MessageComposer` object from `stream-chat`, such as `channel.messageComposer`. The component renders that object and calls it when the user types, attaches or sends. [Message composer UI](https://getstream.io/chat/docs/sdk/react/v15/ui/components/message-composer-ui/) explains the parts it renders and which composer it writes into, and [Message composer](https://getstream.io/chat/docs/sdk/react/v15/state/writing-messages/message-composer/) explains the object.

## Best practices

- Render it inside a `Channel` or a `Thread`. It writes into that thread's or channel's composer, and throws outside both.
- Change what is sent in the state layer, not in the component: transform the message with [composer middleware](https://getstream.io/chat/docs/sdk/react/v15/state/writing-messages/composer-middleware/), or replace the request with a `sendMessageRequest` handler, as [Customizing requests](https://getstream.io/chat/docs/sdk/react/v15/state/writing-messages/message-operations/#customizing-requests) shows.
- Change the look with `WithComponents`. Scope the override around one `MessageComposer` when only that composer should differ.
- To tell a thread composer from a channel one in your own parts, read `useMessageComposerController().threadId`. It's set only for a thread's composer.

## Basic usage

```tsx
import {
  Channel,
  ChannelHeader,
  MessageComposer,
  MessageList,
  Thread,
  ThreadHeader,
} from "stream-chat-react";

export const ChannelPane = () => (
  <Channel channel={channel}>
    <ChannelHeader />
    <MessageList />
    <MessageComposer audioRecordingEnabled />
  </Channel>
);

export const ThreadPane = () => (
  <Thread thread={thread}>
    <ThreadHeader />
    <MessageList />
    <MessageComposer focus />
  </Thread>
);
```

The first composer writes into `channel.messageComposer`, the second into `thread.messageComposer`.

## UI customization

`MessageComposer` renders the component registered as `MessageComposerUI`, and provides [`MessageComposerContext`](https://getstream.io/chat/docs/sdk/react/v15/component-reference/message-composer/messagecomposercontext/) to it. The default `MessageComposerUI` is built from parts, each with an override key of its own:

- To replace one part, such as the send button or the attachment selector, register it under its key. [Message composer UI](https://getstream.io/chat/docs/sdk/react/v15/ui/components/message-composer-ui/#replacing-parts) lists the keys, and [Composer UI components](https://getstream.io/chat/docs/sdk/react/v15/component-reference/message-composer/composer-ui-components/) has their props.
- To replace the whole layout, register your own `MessageComposerUI`. See [Input UI](https://getstream.io/chat/docs/sdk/react/v15/component-reference/message-composer/input-ui/).

When unmounted, `MessageComposer` saves a draft of the composer if drafts are turned on, and then clears the thread's or channel's composer. See [Drafts](https://getstream.io/chat/docs/sdk/react/v15/features/messaging/drafts/).

## Supplying a composer

By default, `MessageComposer` writes into the composer of the thread or channel it's rendered in. Wrap it in `MessageComposerControllerProvider` to have it write into a composer you create instead, for example one that edits a message where it sits. Every `MessageComposer` and composer hook below the provider uses the supplied composer.

A supplied composer belongs to you:

- When `MessageComposer` unmounts, it saves the composer's draft if drafts are on for it, but it never clears the composer. Clear it yourself when the composition ends.
- Submitting works as for any composer: `MessageComposer.update()` while a message is being edited, `MessageComposer.send()` otherwise.

### Edit a message inline

An edit composer has the message as its composition context. This one shows a `MessageComposer` for the message while the edit is in progress:

```tsx
import { useState } from "react";
import type { LocalMessage, MessageComposerState } from "stream-chat";
import { MessageComposer as MessageComposerController } from "stream-chat";
import {
  MessageComposer,
  MessageComposerControllerProvider,
  useChatContext,
  useStateStore,
} from "stream-chat-react";

const editingSelector = (state: MessageComposerState) => ({
  isEditing: state.editedMessage !== null,
});

export const InlineEditor = ({ message }: { message: LocalMessage }) => {
  const { client } = useChatContext();
  const [composer] = useState(
    () =>
      new MessageComposerController({
        client,
        composition: message,
        compositionContext: message,
      }),
  );
  const { isEditing } = useStateStore(composer.state, editingSelector);

  if (!isEditing) return null;

  return (
    <MessageComposerControllerProvider messageComposerController={composer}>
      <MessageComposer />
    </MessageComposerControllerProvider>
  );
};
```

Saving the edit, or cancelling it with the ✕ on the edit preview, empties the composer, and the editor disappears. [Editing a message in place](https://getstream.io/chat/docs/sdk/react/v15/features/messaging/sending-editing-and-deleting/#editing-a-message-in-place) shows where to render it and how to open it from the Edit action.

## Props

| Prop                            | Type                                                                                                          | Default             | Description                                                                                                                                                                                                                                                             |
| ------------------------------- | ------------------------------------------------------------------------------------------------------------- | ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `additionalTextareaProps`       | `Omit<React.TextareaHTMLAttributes<HTMLTextAreaElement>, "defaultValue" \| "style" \| "disabled" \| "value">` | none                | Props for the `<textarea>` that `TextareaComposer` renders. A `placeholder` here replaces "Send a message". The input sets its own `className`, `onBlur`, `onChange`, `onKeyDown`, `onPaste`, `onScroll` and `onSelect`, so those are ignored here.                     |
| `asyncMessagesMultiSendEnabled` | `boolean`                                                                                                     | `false`             | Keeps a finished voice recording in the composer, to send with the rest of the message. Without it, the recording is sent as soon as the user finishes it.                                                                                                              |
| `audioRecordingConfig`          | `CustomAudioRecordingConfig`                                                                                  | none                | Settings for the voice recorder. See [Audio Recorder](https://getstream.io/chat/docs/sdk/react/v15/component-reference/voice-recording/audio-recorder/).                                                                                                                                    |
| `audioRecordingEnabled`         | `boolean`                                                                                                     | `false`             | Shows the record button while the composer is empty, nothing is being edited, no command is active and the browser can record.                                                                                                                                          |
| `emojiSearchIndex`              | `EmojiSearchIndex`                                                                                            | the override        | Put into `MessageComposerContext`, falling back to the `emojiSearchIndex` key of `WithComponents`. No built-in component reads it. Emoji autocomplete comes from a middleware; see [Emoji](https://getstream.io/chat/docs/sdk/react/v15/features/rich-content/emoji/#turning-it-on-or-off). |
| `focus`                         | `boolean`                                                                                                     | `false`             | Focuses the input on mount, and again whenever the attachments or the quoted message change.                                                                                                                                                                            |
| `hideSendButton`                | `boolean`                                                                                                     | `false`             | Removes the control after the input: the send button, the cooldown timer and the record button. While an AI reply is being generated and the stop button isn't turned off, the control still shows.                                                                     |
| `maxRows`                       | `number`                                                                                                      | `10`                | The most rows the input grows to.                                                                                                                                                                                                                                       |
| `minRows`                       | `number`                                                                                                      | none                | The fewest rows the input shows. Without it, an empty input is one row high.                                                                                                                                                                                            |
| `parent`                        | `LocalMessage`                                                                                                | none                | Put into `MessageComposerContext` for your own parts. The SDK doesn't read it: inside a `Thread`, the composer is the thread's.                                                                                                                                         |
| `shouldSubmit`                  | `(event: React.KeyboardEvent<HTMLTextAreaElement>) => boolean`                                                | Enter without Shift | Decides which key press submits. The default submits on Enter without Shift, and not while an input method is composing text.                                                                                                                                           |

`MessageComposer` puts these props into [`MessageComposerContext`](https://getstream.io/chat/docs/sdk/react/v15/component-reference/message-composer/messagecomposercontext/), where its parts read them.

## Hooks

- [`useMessageComposerController`](https://getstream.io/chat/docs/sdk/react/v15/reference/hooks/composer-hooks/#usemessagecomposercontroller): the composer a component writes into.
- [`useMessageComposerContext`](https://getstream.io/chat/docs/sdk/react/v15/reference/hooks/composer-hooks/#usemessagecomposercontext): the props above and the input's bindings.
- [`useMessageComposerSubmitFn`](https://getstream.io/chat/docs/sdk/react/v15/reference/hooks/composer-hooks/#usemessagecomposersubmitfn): submits the composition the way the send button does.

[Composer hooks](https://getstream.io/chat/docs/sdk/react/v15/reference/hooks/composer-hooks/) lists the rest.

---

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