Info:
This is release candidate documentation for Stream Chat React SDK v15. For the latest stable version, see the latest version (v14).

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() and useStateStore, not from this context.
  • Read the cooldown with useIsCooldownActive or useCooldownRemaining, or render CooldownTimer. It isn't in this context.
  • This context doesn't decide which composer is used. To have MessageComposer write 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, and useIsWithinMessageComposerContext() 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