Upgrade to v13

Removal of StreamChatGenerics

See the release guide of stream-chat and TypeScript & Custom Data Types article.

Changes in Message Types

Introduction of LocalMessage type

MessageToSend, StreamMessage, and UpdatedMessage were removed and replaced by LocalMessage. LocalMessage represents the message stored in local state. Server responses (MessageResponse) are converted to LocalMessage immediately.

Introduction of RenderedMessage type

RenderedMessage includes LocalMessage plus client-side ephemeral messages like DateSeparatorMessage and IntroMessage.

Change in Message Composition

Message composition is now managed by MessageComposer instances. Each composition context has its own composer:

  • channel - for main channel list message composition
  • thread - for message composition in Thread view
  • legacy_thread - for the legacy side-by-side thread layout next to the channel list
  • message - for editing a message in any message list

Get the current composer with useMessageComposer.

Introduction of MessageComposer leads to breaking changes described in the following sections.

Replaced Text Autocomplete Components

The following components were removed and replaced:

RemovedReplaced by
AutoCompleteTextareaTextAreaComposer
ChatAutoCompleteTextAreaComposer
DefaultSuggestionListSuggestionList
DefaultSuggestionListItemSuggestionListItem

ChatAutoComplete (which rendered AutoCompleteTextarea) was replaced by TextAreaComposer.

Removed MessageInput, ChatAutoComplete, and AutoCompleteTextarea Props

The following props previously exposed on ChatAutoComplete and AutoCompleteTextarea are no longer available.

AutoCompleteTextarea

PropReplacement
containerStyleApply custom styles using CSS
defaultValueSet via MessageComposer configuration (text.defaultValue) (see the composer configuration guide) or via the TextComposer.defaultValue setter.
disabledSet via MessageComposer configuration (text.enabled) (see the composer configuration guide)
disableMentionsRemove mentions middleware from the TextComposer.middlewareExecutor (see the composer middleware guide)
dropdownClassNameOverride prop containerClassName directly on SuggestionList and pass the list component as AutocompleteSuggestionList to Channel
dropdownStyleApply custom styles using CSS
itemClassNameOverride prop className directly on SuggestionListItem and pass the item component as AutocompleteSuggestionItem to Channel
itemStyleApply custom styles using CSS
listClassNameOverride prop className directly on SuggestionList and pass the list component as AutocompleteSuggestionList to Channel
listStyleApply custom styles using CSS
loaderClassNameThe prop was not used. No replacement provided.
loaderStyleThe prop was not used. No replacement provided.
loadingComponentThe prop was not used. No replacement provided.
growRedundant prop. Use prop maxRows to indicate up to what number of rows the textarea can grow.
onCaretPositionChangeSubscribe to TextComposer.state and observe selection (see the state store guide)
onSelectAdd custom middleware to TextComposer.middlewareExecutor to handle onSuggestionItemSelect event (see the composer middleware guide)
styleApply custom styles using CSS
triggerThe current trigger value is signaled via TextComposer.state.suggestions
valueThe current (text) value is signaled via TextComposer.state.text

ChatAutoComplete

The component used to forward props to AutoCompleteTextarea. As those are already described in the previous section, we will omit them in the below table.

PropReplacement
handleSubmitCustomize composition via MessageComposer.compositionMiddlewareExecutor and draft composition via MessageComposer.draftCompositionMiddlewareExecutor (see the composer middleware guide). Sending can be customized via the Channel prop doSendMessageRequest.
wordReplaceEmoji replacement now happens in TextComposer middleware via onChange. The built-in emoji middleware covers this (see the composer middleware guide).

MessageInput

PropReplacement
doFileUploadRequestCustom upload function can be configured via MessageComposer configuration (attachments.doUploadRequest) or MessageComposer.attachmentManager.setCustomUploadFn method.
doImageUploadRequestCustom upload function can be configured via MessageComposer configuration (attachments.doUploadRequest) or MessageComposer.attachmentManager.setCustomUploadFn method.
errorHandlerTo handle errors thrown during the file upload, subscribe to client.notifications.state and react to notification.message 'Error uploading attachment'.
getDefaultValueThe default value is set via MessageComposer configuration (text.defaultValue) (see the composer configuration guide) or set reactively via TextComposer.defaultValue setter
mentionAllAppUsersMentions configuration can be done via TextComposer mentions middleware ( createMentionsMiddleware(channel, {searchSource: new MentionsSearchSource(channel, {mentionAllAppUsers: true}) })
mentionQueryParamsOverride methods MentionsSearchSource.prepareQueryUsersParams or MentionsSearchSource.prepareQueryMembersParams respectively to generate filter, sort and options objects to perform user and member requests based on search text.
messageMessageComposer is automatically provided with the edited message. No replacement.
noFilesCustom logic to filter files can be specified via MessageComposer configuration (attachments.fileUploadFilter) or MessageComposer.attachmentManager.fileUploadFilter setter.
parentThe parent message is automatically provided to the MessageComposer. No replacement.
publishTypingEventConfigure with MessageComposer.textComposer.publishTypingEvents
urlEnrichmentConfigThe link preview config can be specified via MessageComposer.linkPreviews configuration or MessageComposer.linkPreviewsManager setters
useMentionsTransliterationMentions configuration can be done via TextComposer mentions middleware ( createMentionsMiddleware(channel, {searchSource: new MentionsSearchSource(channel, {transliterate: (textToTransliterate: string) => string}) })

Further, the signature of function passed to overrideSubmitHandler has changed. It now accepts a single object parameter:

type overrideSubmitHandler = (params: {
  cid: string;
  localMessage: LocalMessage;
  message: Message;
  sendOptions: SendMessageOptions;
}) => Promise<void> | void;

Removed Channel Props

PropReplacement
acceptedFilesThe array of strings can be specified via MessageComposer configuration (attachments.acceptedFiles) or MessageComposer.attachmentManager.acceptedFiles setter.
enrichURLForPreview, enrichURLForPreviewConfigThe link preview config can be specified via MessageComposer.linkPreviews configuration or MessageComposer.linkPreviewsManager setters.
maxNumberOfFilesCan be specified via MessageComposer configuration (attachments.maxNumberOfFilesPerMessage) or MessageComposer.attachmentManager.maxNumberOfFilesPerMessage setter.
multipleUploadsDoes not have replacement. Multiple uploads are inferred from configuration parameter maxNumberOfFilesPerMessage value greater than 1.
TriggerProviderTriggers are characters in composed message text that cause suggestions to be rendered (emoji, mentions, commands). This component served to propagate potentially custom trigger logic. This is however now done via TextComposer.middlewareExecutor by providing custom middleware functions (see the composer middleware guide).

Autocomplete trigger logic migration

Autocomplete triggers are now handled by TextComposer middleware in stream-chat. The following types were removed from stream-chat-react:

  • SuggestionHeaderProps
  • ChatAutoCompleteProps
  • AutocompleteMinimalData
  • CommandTriggerSetting
  • EmojiTriggerSetting
  • UserTriggerSetting
  • TriggerSetting
  • TriggerSettings

This migration also led to removal of the trigger generic parameter from stream-chat-react components. Typed text now flows through middleware before it is committed to MessageComposer state.

ChannelActionContext Changes

Besides the LocalMessage change for editMessage, openThread, removeMessage, and updateMessage, the following changes apply:

The sendMessage function signature has changed. Now it accepts a single object parameter:

type sendMessage = (params: {
  localMessage: LocalMessage;
  message: Message;
  options?: SendMessageOptions;
}) => Promise<void>;

setQuotedMessage was removed. Quoted message state is now handled by MessageComposer, via MessageComposer.setQuotedMessage(quotedMessage: LocalMessage | null).

ChannelStateContext Changes

Removed Channel props are now absent from ChannelStateContext too: acceptedFiles, enrichURLForPreview, parts of enrichURLForPreviewConfig (debounceURLEnrichmentMs, findURLFn, onLinkPreviewDismissed), and multipleUploads.

PropReplacement
quotedMessageValue changes can now be observed by subscribing to MessageComposer.state changes.
const messageComposerStateSelector = (state: MessageComposerState) => ({
  quotedMessage: state.quotedMessage,
});
const messageComposer = useMessageComposer();
const { quotedMessage } = useStateStore(
  messageComposer.state,
  messageComposerStateSelector,
);

useMessageInputState → useMessageInputControls

Message composition state moved from stream-chat-react to stream-chat and MessageComposer. As a result, useMessageInputState was renamed to useMessageInputControls and now exposes only the following API via MessageInputContext:

  • handleSubmit - Also received an overhaul resulting in signature change (see below).
  • onPaste
  • recordingController
  • textareaRef

Message input state and most of the API now live in MessageComposer, not MessageInputContext.

MessageInputContext Changes

With the useMessageInputState refactor:

1. Context Values Removed

PropReplacement
insertTextUse MessageComposer.textComposer.insertText method
handleChangeUse MessageComposer.textComposer.handleChange method
isUploadEnabledUse useAttachmentManagerState hook to subscribe to isUploadEnabled value changes
maxFilesLeftUse useAttachmentManagerState hook to subscribe to availableUploadSlots value changes
numberOfUploadsUse useAttachmentManagerState hook to subscribe to successfulUploadsCount and uploadsInProgressCount value changes
onSelectUserUse MessageComposer.textComposer.handleSelect method to announce a suggestion item has been selected. It is possible to register custom TextComposer middleware (see the middleware guide).
removeAttachmentsUse MessageComposer.attachmentManager.removeAttachments method
uploadAttachmentUse MessageComposer.attachmentManager.uploadAttachment method
uploadNewFilesUse MessageComposer.attachmentManager.uploadFiles method
upsertAttachmentsUse MessageComposer.attachmentManager.upsertAttachments method
closeCommandsListUse MessageComposer.textComposer.closeSuggestions method
openCommandsListDone automatically upon trigger identification. You can register custom TextComposer onChange middleware or override trigger characters (see the middleware guide).
showCommandsListCheck whether the command list is open via TextComposer.suggestions?.trigger === commandTrigger
closeMentionsListUse MessageComposer.textComposer.closeSuggestions method
openMentionsListDone automatically upon trigger identification. We can register a custom TextComposer middleware for onChange event to introduce custom logic, or override the mentions trigger character(s) (see the middleware guide).
showMentionsListCheck whether the mentions list is open via TextComposer.suggestions?.trigger === mentionTrigger

The removed values forwarded from MessageInputProps to MessageInputContext have been documented above.

2. handleSubmit Signature Change

handleSubmit now accepts only an optional event object. The customMessageData and options parameters were removed.

Before:

type handleSubmit = (
  event?: React.BaseSyntheticEvent,
  customMessageData?: Partial<Message<StreamChatGenerics>>,
  options?: SendMessageOptions,
) => Promise<void>;

Now:

type handleSubmit = (event?: React.BaseSyntheticEvent) => Promise<void>;

Custom message data can be injected via middleware (see the middleware guide) or by setting it directly:

messageComposer.customDataManager.setMessageData({ a: "b" });

Attachment Identity Functions Moved to stream-chat

The following identity functions were moved to stream-chat:

Original NameNew Name
isLocalAttachmentisLocalAttachment
isScrapedContentisScrapedContent
noneisLocalUploadAttachment
isFileAttachmentisFileAttachment
isLocalFileAttachmentisLocalFileAttachment
isUploadedImageisImageAttachment
noneisLocalImageAttachment
isAudioAttachmentisAudioAttachment
isLocalAudioAttachmentisLocalAudioAttachment
isVoiceRecordingAttachmentisVoiceRecordingAttachment
isLocalVoiceRecordingAttachmentisLocalVoiceRecordingAttachment
isMediaAttachmentisVideoAttachment
isLocalMediaAttachmentisLocalVideoAttachment
noneisUploadedAttachment

isGalleryAttachmentType remains in stream-chat-react because it’s SDK-specific.

Message Composition Changes Summary

Message composition is now handled by the MessageComposer class. Use useMessageComposer to get the correct instance for the current context.

APIs moved to MessageComposer were removed from the relevant React contexts and component props in stream-chat-react.

Removal of Channel.dragAndDropWindow Prop

The Channel prop dragAndDropWindow and associated optionalMessageInputProps were removed. Use WithDragAndDropUpload instead.