# MessageInput

`MessageInput` wraps the logic, state, and UI for composing messages. It provides [`MessageInputContext`](/chat/docs/sdk/react/v13/components/contexts/message_input_context/) to its children, which all input UI components consume.

## Best Practices

- Keep `MessageInput` under `Channel` so context and actions are available.
- Use custom `Input` only when you need layout changes, not minor styling.
- Prefer composer middleware over `overrideSubmitHandler` for message logic.
- Avoid deprecated `isThreadInput`; rely on `messageComposer.threadId`.
- Keep textarea row limits aligned with your UX guidelines.

## Basic Usage

`MessageInput` must be rendered under `Channel`. It has no required props and builds `MessageInputContext` using internal hooks.

<admonition type="note">

If you don’t pass a custom `Input`, [`MessageInputFlat`](https://github.com/GetStream/stream-chat-react/blob/master/src/components/MessageInput/MessageInputFlat.tsx) is used by default.

</admonition>

```tsx
<Chat client={client}>
  <ChannelList />
  <Channel>
    <MessageList />
    <MessageInput />
  </Channel>
</Chat>
```

## UI Customization

`MessageInput` doesn’t render UI itself; customization is handled by the [Input UI component](/chat/docs/sdk/react/v13/components/message-input-components/input_ui/) passed via the `Input` prop on `Channel` or `MessageInput`.

## Props

### additionalTextareaProps

Additional props to be consumed by the underlying `TextareaComposer` component.

```ts
type additionalTextareaProps = Omit<
  React.TextareaHTMLAttributes<HTMLTextAreaElement>,
  "defaultValue" | "style" | "disabled" | "value"
>;
```

### clearEditingState

Function to clear the editing state while editing a message.

| Type       |
| ---------- |
| () => void |

### focus

If true, focuses the text input on component mount.

| Type    | Default |
| ------- | ------- |
| boolean | false   |

### hideSendButton

Allows to hide MessageInput's send button. Used by `MessageSimple` to hide the send button in `EditMessageForm`.

| Type    | Default |
| ------- | ------- |
| boolean | false   |

### Input

Custom UI component handling how the message input is rendered.

| Type      | Default                                                                                                                         |
| --------- | ------------------------------------------------------------------------------------------------------------------------------- |
| component | [MessageInputFlat](https://github.com/GetStream/stream-chat-react/blob/master/src/components/MessageInput/MessageInputFlat.tsx) |

### isThreadInput

Signals that the MessageInput is rendered in a message thread (Thread component).
This prop is deprecated. Use `messageComposer.threadId` to determine whether a thread reply is being composed.

| Type    |
| ------- |
| boolean |

### maxRows

Max number of rows the underlying `textarea` component is allowed to grow.

| Type   | Default |
| ------ | ------- |
| number | 10      |

### minRows

Min number of rows the underlying `textarea` will start with.

| Type   | Default |
| ------ | ------- |
| number | 1       |

### overrideSubmitHandler

Function to override the default submit handler. This isn’t intended for message composition; use custom composition middleware instead (guide here: /chat/docs/sdk/react/v13/components/message-input-components/message-composer-middleware#message-composer-middleware-overview).

```ts
type overrideSubmitHandler = (params: {
  cid: string; // target channel CID
  localMessage: LocalMessage; // object representing the local message data used for UI update
  message: Message; // object representing the payload sent to the server for message creation / update
  sendOptions: SendMessageOptions;
}) => Promise<void> | void;
```

```tsx
import { MessageInput } from "stream-chat-react";
import type { MessageInputProps } from "stream-chat-react";

const CustomMessageInput = (props: MessageInputProps) => {
  const submitHandler: MessageInputProps["overrideSubmitHandler"] = useCallback(
    async (params: {
      cid: string;
      localMessage: LocalMessage;
      message: Message;
      sendOptions: SendMessageOptions;
    }) => {
      // custom logic goes here

      await sendMessage({ localMessage, message, options: sendOptions });
    },
    [sendMessage],
  );

  return (
    <StreamMessageInput {...props} overrideSubmitHandler={submitHandler} />
  );
};
```

### parent

When replying in a thread, the parent message object.

| Type   |
| ------ |
| object |

### shouldSubmit

Currently, `Enter` is the default submission key and `Shift`+`Enter` is the default combination for the new line.
If specified, this function overrides the default behavior specified previously.

| Type                              |
| --------------------------------- |
| (event: KeyboardEvent) => boolean |

<admonition type="note">

### Migration from versions older than `9.0.0`

Property **keycodeSubmitKeys** has been replaced by **shouldSubmit** and thus is no longer supported.
If you had custom key codes specified like so:

```ts
keyCodeSubmitKeys={[[16,13], [57], [48]]} // submission keys are Shift+Enter, 9, and 0
```

then that would newly translate to:

```ts
const shouldSubmit = (event) =>
  (event.key === 'Enter' && event.shiftKey) || event.key === '9' || event.key === '0';

...

shouldSubmit={shouldSubmit}
```

</admonition>


---

This page was last updated at 2026-04-21T09:53:40.597Z.

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