MessageComposerContext
MessageComposerContext holds the props of the MessageComposer around a component, and the bindings of its input: the textarea ref, the paste handler and the voice recorder. Every part of the composer UI can read it with useMessageComposerContext(). It holds UI settings, not the message: the text, the attachments and the rest are in the composer's stores, which Message composer UI maps to the parts that read them.
Best practices
- Read the message being written from the composer, with
useMessageComposerController()anduseStateStore, not from this context. - Read the cooldown with
useIsCooldownActiveoruseCooldownRemaining, or renderCooldownTimer. It isn't in this context. - This context doesn't decide which composer is used. To have
MessageComposerwrite into a composer you own, see Supplying a composer. - Render components that read it inside
MessageComposer, for example as an override of one of its parts.useMessageComposerContext()throws outside it, anduseIsWithinMessageComposerContext()tells whether a component is inside one.
Basic usage
This composer UI shows a hint below the default UI when the user has blocked the microphone:
import {
MessageComposer,
MessageComposerUI,
useMessageComposerContext,
WithComponents,
} from "stream-chat-react";
const ComposerUIWithMicrophoneHint = () => {
const { audioRecordingEnabled, recordingController } =
useMessageComposerContext();
const microphoneBlocked =
audioRecordingEnabled && recordingController.permissionState === "denied";
return (
<>
<MessageComposerUI />
{microphoneBlocked && (
<p className="composer-hint">
Allow the microphone to record voice messages.
</p>
)}
</>
);
};
const overrides = { MessageComposerUI: ComposerUIWithMicrophoneHint };
export const ComposerWithHint = () => (
<WithComponents overrides={overrides}>
<MessageComposer audioRecordingEnabled />
</WithComponents>
);Values
| Value | Type | Description |
|---|---|---|
additionalTextareaProps |
Omit<React.TextareaHTMLAttributes<HTMLTextAreaElement>, "defaultValue" | "style" | "disabled" | "value"> |
The MessageComposer prop. TextareaComposer spreads it onto the <textarea>. |
asyncMessagesMultiSendEnabled |
boolean | undefined |
The MessageComposer prop: whether a finished voice recording stays in the composer instead of being sent. |
audioRecordingConfig |
CustomAudioRecordingConfig | undefined |
In the type, but always undefined. The recorder in recordingController gets the MessageComposer prop directly. |
audioRecordingEnabled |
boolean | undefined |
The MessageComposer prop: whether voice recording is turned on. |
emojiSearchIndex |
EmojiSearchIndex | undefined |
The MessageComposer prop, or the emojiSearchIndex key of WithComponents. No built-in component reads it. |
focus |
boolean | undefined |
The MessageComposer prop. TextareaComposer focuses the input on mount, and again whenever the attachments or the quoted message change. |
hideSendButton |
boolean | undefined |
The MessageComposer prop. MessageComposerActions renders nothing while it's set, unless an AI reply can be stopped. |
maxRows |
number | undefined |
The MessageComposer prop. TextareaComposer uses 10 when neither it nor its own maxRows is set. |
minRows |
number | undefined |
The MessageComposer prop. |
onPaste |
(event: React.ClipboardEvent<HTMLTextAreaElement>) => void |
The paste handler of the input. It inserts pasted text, or uploads the pasted files when there's no text. |
parent |
LocalMessage | undefined |
The MessageComposer prop. No built-in component reads it. |
recordingController |
RecordingController |
The voice recorder: recorder, the recording in progress, recordingState, the microphone permissionState, and completeRecording(). recorder is undefined unless audioRecordingEnabled is set. |
shouldSubmit |
((event: React.KeyboardEvent<HTMLTextAreaElement>) => boolean) | undefined |
The MessageComposer prop. |
textareaRef |
React.RefObject<HTMLTextAreaElement | null | undefined> |
The ref of the input's <textarea>, set by TextareaComposer. Use it to focus the input. |
While recordingController.recordingState is set, the default MessageComposerUI renders AudioRecorder in place of the input. See Audio Recorder.
Examples
Read the cooldown
The cooldown isn't in the context. Read whether it's on with its hook:
import { CooldownTimer, useIsCooldownActive } from "stream-chat-react";
export const ComposerFooter = () => {
const isCooldownActive = useIsCooldownActive();
if (!isCooldownActive) return null;
return <CooldownTimer />;
};useIsCooldownActive() re-renders only when the wait starts or ends; CooldownTimer counts the seconds itself. Both read channel.cooldownTimer, so they need a Channel or a Thread around them. useCooldownRemaining() returns the seconds left, for a countdown of your own. See Slow mode.
Insert text and focus the input
A part that writes into the composer gets the composer from useMessageComposerController() and the input from textareaRef:
import {
AdditionalMessageComposerActions,
useMessageComposerContext,
useMessageComposerController,
} from "stream-chat-react";
export const ActionsWithGreeting = () => {
const { textareaRef } = useMessageComposerContext();
const { textComposer } = useMessageComposerController();
const greet = () => {
textComposer.insertText({ text: "Hi there! " });
textareaRef.current?.focus();
};
return (
<>
<button onClick={greet} type="button">
Greet
</button>
<AdditionalMessageComposerActions />
</>
);
};Register it as AdditionalMessageComposerActions with WithComponents. It renders the default part too, so the emoji picker stays.
Hooks
useMessageComposerContextreturns this context.useMessageComposerControllerreturns the composer itself.useMessageComposerBindingscreatestextareaRef,onPasteandrecordingController, for a replacement ofMessageComposeritself.