# MessageComposer Class

## MessageComposer Class

<partial id="shared/chat/js/message-composer/_introduction"></partial>

## Best Practices

- Configure `MessageComposer` once and reuse it across channel/thread contexts.
- Apply middleware via `setMessageComposerSetupFunction` to keep behavior consistent.
- Scope middleware by `contextType` to avoid unintended side effects.
- Keep custom configuration minimal and document any overrides.
- Use composer managers (text, attachments, polls) instead of duplicating state.

### Message Composer Setup

There can be multiple `MessageComposer` instances at once (main channel, thread, edit mode, etc.). They’re initialized from `Channel` and `Thread`, so setup changes must happen after initialization. Use `StreamChat.setMessageComposerSetupFunction` to apply changes to existing and future composers. Call it once, or re-run only when a dependency changes.

In the example below, we configure middleware for all `MessageComposer` instances:

```tsx
import { useState, useEffect } from "react";
import { useCreateChatClient } from "stream-chat-react";
import { createTextComposerEmojiMiddleware } from "stream-chat-react/emojis";
import { init, SearchIndex } from "emoji-mart";
import data from "@emoji-mart/data";

init({ data });

const chatClient = useCreateChatClient({
  apiKey,
  tokenOrProvider: userToken,
  userData: { id: userId, language: "en" },
});

const [emojisEnabled, setEmojisEnabled] = useState(false);

useEffect(() => {
  chatClient.setMessageComposerSetupFunction(({ composer }) => {
    if (composer.contextType !== "channel" || !emojisEnabled) return;
    const emojiMiddleware = createTextComposerEmojiMiddleware(SearchIndex);

    composer.textComposer.middlewareExecutor.insert({
      middleware: [emojiMiddleware],
      position: { before: "stream-io/text-composer/mentions-middleware" },
      unique: true,
    });

    return () => {
      composer.textComposer.middlewareExecutor.remove(emojiMiddleware.id);
    };
  });
}, [chatClient, emojisEnabled]);
```

## Message Composer Configuration

<partial id="shared/chat/js/message-composer/_configuration"></partial>

## Message Composer Context Type

Each `MessageComposer` has a `contextType` derived from the `compositionContext` provided at construction. Possible values: `channel`, `thread`, `legacy_thread`, or `message`.

You’ll usually ignore this, but it’s useful when applying middleware only to channel or thread composers.

<admonition type="note">

Type `legacy_thread` is a simple message object extended with `legacyThreadId` property whose value equals to that message's `id`.

</admonition>

## Accessing the Corresponding MessageComposer instance

<partial id="shared/chat/js/message-composer/_message-composer-access-react"></partial>

## Message Composer Utility Hooks

<partial id="shared/chat/js/message-composer/_message-composer-react-hooks"></partial>


---

This page was last updated at 2026-04-13T07:26:58.337Z.

For the most recent version of this documentation, visit [https://getstream.io/chat/docs/sdk/react/v14/components/message-composer/message-composer-class/](https://getstream.io/chat/docs/sdk/react/v14/components/message-composer/message-composer-class/).