Upgrade to v12

Introducing Threads 2.0

With the release of v12 of our SDK we’re also releasing new thread functionality - specifically “thread view”, which consists of ThreadList and Thread components allowing your users to quickly go over threaded conversations they’re part of. To implement this simple view see thread and channel view guide.

Thread & ThreadManager

Both Thread and ThreadManager are new classes within stream-chat package with own logic which updates their respective state objects to which integrators can subscribe to and render their UI accordingly. These classes (or rather instances of these classes) are utilised within React SDK. Read more about accessing state of these classes in our SDK State Management documentation.

ThreadList & ThreadListItem

ThreadList component represents a ThreadManager instance while ThreadListItem represents individual Thread instances. UI of both of these components reflects latest state of their appropriate “controllers” but apart from communicating with their controllers via available methods these components do not manage any extra logic.

ThreadProvider

ThreadProvider is an “adapter” which allows existing Thread component to consume methods and state of the Thread instance.

<ThreadProvider thread={thread}>
  <Thread />
</ThreadProvider>

ChatView & ChatView.ThreadAdapter

ChatView is component itself and a set of components which allow for a drop-in implementation of different chat views - the channel view and thread view. This drop-in solution allows your users to easily switch between said views without having to implement such mechanism yourself. Read more about it in our ChatView documentation.

Introducing WithComponents & Dropping Defaults

We know that component overrides are 90% of our SDK and providing these overrides only through Channel component isn’t optimal. In the upcoming minor releases we’ll be deprecating component overrides through individual component props and rather provide these overrides through WithComponents, you can read more about this component in our WithComponents documentation.

Dropped ComponentContext Defaults

These components are no longer provided through the ComponentContext as default values but have moved to their respective components:

  • Attachment
  • DateSeparator
  • Message
  • MessageSystem
  • reactionOptions
  • UnreadMessagesSeparator

Before and After

Previous solution for component overrides:

const MessageInputUi1 = () => {
  /*...*/
};
const MessageInputUi2 = () => {
  /*...*/
};

<Channel Input={MessageInputUi1}>
  <Window>
    <MessageList />
    <MessageInput focus />
  </Window>
  <Thread Input={MessageInputUi2} virtualized />
</Channel>;

Current solution utilising WithComponents:

const MessageInputUi1 = () => {
  /*...*/
};
const MessageInputUi2 = () => {
  /*...*/
};

<Channel>
  <WithComponents overrides={{ Input: MessageInputUi1 }}>
    <Window>
      <MessageList />
      <MessageInput focus />
    </Window>
    <WithComponents overrides={{ Input: MessageInputUi2 }}>
      <Thread virtualized />
    </WithComponents>
  </WithComponents>
</Channel>;

Audio recordings transcoding

Until now the audio recordings were transcoded to audio/mp3. As of v12, the MIME-type audio/wav will be the default. You can still opt-in to MP3 and benefit from the reduced file size and bandwidth usage:

Action required
To opt into MP3 transcoding follow these steps:

  1. The library @breezystack/lamejs has to be installed as this is a peer dependency to stream-chat-react.
npm install @breezystack/lamejs
yarn add @breezystack/lamejs
  1. The MP3 encoder has to be imported separately as a plugin:
import { MessageInput } from 'stream-chat-react';
import { encodeToMp3 } from 'stream-chat-react/mp3-encoder';

<MessageInput focus audioRecordingConfig={{ transcoderConfig: { encoder: encodeToMp3 } }} />;

Unified dialog management

Dialogs will be managed centrally. At the moment, this applies to display of ReactionSelector and MessageActionsBox. They will be displayed on a transparent overlay that prevents users from opening other dialogs in the message list. Once an option from a dialog is selected or the overlay is clicked, the dialog will disappear. This adjust brings new API and removes some properties from MessageContextValue.

Removed properties from MessageContextValue

  • isReactionEnabled - served to signal the permission to send reactions by the current user in a given channel. With the current permissions implementation, the permission can be determined by doing the following:
import { useMessageContext } from 'stream-chat-react';

const { getMessageActions } = useMessageContext();
const messageActions = getMessageActions();
const canReact = messageActions.includes(MESSAGE_ACTIONS.react);
  • onReactionListClick - handler function that toggled the open state of ReactionSelector represented by another removed value - showDetailedReactions
  • showDetailedReactions - flag used to decide, whether the reaction selector should be shown or not
  • reactionSelectorRef - ref to the root of the reaction selector component (served to control the display of the component)

Also prop messageWrapperRef was removed as part of the change from MessageOptions and MessageActions props.

On the other hand, the Message prop (configuration parameter) closeReactionSelectorOnClick is now available in the MessageContextValue.

If you used any of these values in your customizations, please make sure to adjust your implementation according to the newly recommended use of Dialog API in Dialog management guide.

New dialog management API

To learn about the new API, please, take a look at our Dialog management guide.

EmojiPickerIcon extraction to emojis plugin

The default EmojiPickerIcon has been moved to emojis plugin from which we already import EmojiPicker component.

Action required
In case you are importing EmojiPickerIcon in your code, make sure to adjust the import as follows:

import { EmojiPickerIcon } from 'stream-chat-react/emojis';

Removal of duplicate uploads state in MessageInput

As of the version 12 of stream-chat-react the MessageInputContext will not expose the following state variables:

  • fileOrder - An array of IDs for non-image uploaded attachments. Its purpose was just to keep order in which the attachments were added.
  • imageOrder - An array of IDs for image uploaded attachments. Its purpose was just to keep order in which the attachments were added.
  • fileUploads - A mapping of ID to attachment representing the uploaded non-image file.
  • imageUploads - A mapping of ID to attachment representing the uploaded image file.

These four variables’ purpose was to render the attachment previews in a given order. All the non-image attachments were assigned type "file" until the message was sent at which point the audio files were assigned type "audio" and video file type "video". Also, the attachment objects structure used to change upon submission. Some keys were renamed and other just removed.

The shortcomings of the above approach have been adjusted as follows:

  1. All the attachments except the link preview attachments (objects that contain og_scrape_url attribute) are now stored in attachments array of MessageInputContext. Array keeps order and the attachment type can be determined by the attachment.type property.

  2. The previously removed “local” data is now stored on each attachment object under localMetadata key. This key is removed upon submission. Every localMetadata object has to at least contain the id attribute that allows us to update or remove the given attachment from the state. The attachments that represent an uploaded file has to also include the localMetadata.file reference.

  3. Attachments representing uploaded files will be identified by the file attribute as attachment.localMetadata.file. Default attachment types recognized by the SDK are:

  • audio
  • file
  • image
  • video
  • voiceRecording
  1. The attachment type is assigned upon the upload and not upon the submission. Also, there is no renaming of attachment attributes upon submission, but the attachment objects are assigned the attributes that are kept from the upload until the submission. These attributes are:

  2. We have removed the following API tied to uploads state from the MessageInput state

  • uploadFile -> from now on, use uploadAttachment
  • uploadImage -> from now on, use uploadAttachment
  • removeFile -> from now on, use removeAttachments
  • removeImage -> from now on, use removeAttachments

The function uploadNewFiles has been kept.

To sum up, the attachments management API in MessageInput is from now on only:

  • attachments - An array that keeps all the message attachment objects except for link previews that should be accessed via linkPreviews (see the guide on how to use linkPreviews).
  • uploadAttachment - Uploads a single attachment. The provided attachment should contain a localMetadata object with file (references a File instance to be uploaded) and id properties.
  • uploadNewFiles - Expects an array of File or Blob objects, generates an array of well-formed attachments and uploads the files with uploadAttachment function
  • upsertAttachments - Expects an array of attachment object where each of those should contain localMetadata.id. Creates or updates the attachment attributes based on the given id in the attachments array of MessageInputContext.
  • removeAttachments - Expects and array of strings representing attachment IDs and removes those attachment objects from the state.

Action required
Make sure you are not using any of the removed API elements (for example you have implemented a custom AttachmentPreviewList):

  • fileOrder
  • imageOrder
  • fileUploads
  • imageUploads
  • uploadFile
  • uploadImage
  • removeFile
  • removeImage

Date & time formatting

The components that display date and time are:

  • DateSeparator - separates message groups in message lists
  • EventComponent - displays system messages
  • MessageTimestamp - displays the creation timestamp for a message in a message list

These components had previously default values for props like format or calendar. This setup required for a custom formatting to be set up via i18n service, the default values had to be nullified. For a better developer experience we decided to remove the default prop values and rely on default configuration provided via i18n translations. The value null is not a valid value for format, calendar or calendarFormats props.

Action required
If you are not using the default translations provided with the SDK, make sure to follow the date & time formatting guide to verify that your dates are formatted according to your needs.

Avatar changes

The Avatar styles are applied through CSS from the version 12 upwards. Therefore, the following changes were applied:

  1. Props shape and size were removed. Subsequently, the class str-chat__avatar--${shape} was removed.

  2. Another class we removed is str-chat__avatar-image--loaded that was applied to img element in the Avatar component.

  3. New prop className has been added to Avatar. Integrators can now optionally apply custom styles to custom classes.

  4. There have also been added new classes to Avatar root div in different components:

ComponentAvatar root CSS class
ChannelHeaderstr-chat__avatar--channel-header
ChannelPreviewMessengerstr-chat__avatar--channel-preview
MessageStatusstr-chat__avatar--message-status
ReactionsListstream-chat__avatar--reaction
QuotedMessagestr-chat__avatar--quoted-message-sender
SearchResultItemstr-chat__avatar--channel-preview
UserItem rendered by SuggestionListItemstr-chat__avatar--autocomplete-item
  1. As a consequence of the Avatar props changes, the TypingIndicator prop avatarSize have been removed as well.

Action required
1. Migrate CSS applied to .str-chat__avatar--${shape} or re-apply the class through Avatar className prop.
2. Migrate CSS applied to .str-chat__avatar-image--loaded to .str-chat__avatar-image class.
3. If needed, apply custom styles to newly added classes based on the component that renders the Avatar.

Removal of styling props

Removal of Window’s hideOnThread prop

The prop boolean hideOnThread enabled us to control, whether class str-chat__main-panel--hideOnThread was attached to Window component’s root <div/>. By assigning this class a CSS rule display: none in the default SDK’s stylesheet we hid the contents of Window. We decided to simplify the logic in this case:

  1. class str-chat__main-panel--hideOnThread was replaced by class str-chat__main-panel--thread-open
  2. the class str-chat__main-panel--thread-open is attached to the root <div/> always, when thread is open
  3. the default value of hideOnThread prop was false (Window contents was not hidden upon opening a thread) and so integrators still have to opt in to hiding the contents upon opening a thread by adding rule display: none to str-chat__main-panel--thread-open class

Action required If your application renders Window with hideOnThread enabled, and you want to keep this behavior add the following rule to your CSS:

.str-chat__main-panel--thread-open {
  display: none;
}

.str-chat__main-panel--thread-open + .str-chat__thread {
  // occupy the whole space previously occupied by the main message list container
  flex: 1;
}

Removal of Thread’s fullWidth prop

Setting the fullWidth value to true let to assignment of class str-chat__thread--full to the Thread component’s root <div/>. This class had support in the SDK’s legacy stylesheet only. With the approach of avoiding styling React components via props, the prop has been removed along with the legacy stylesheet. Read more about the the stylesheet removal in the section Removal of deprecated components.

Removal of deprecated components

Attachment rendering utility functions

The attachment rendering functions were replaced with their component equivalents:

Action required
Replace the render functions in your custom components with container components alternatives.

Rendering functionComponent equivalent
renderAttachmentWithinContainerAttachmentWithinContainer
renderAttachmentActionsAttachmentActionsContainer
renderGalleryGalleryContainer
renderImageImageContainer
renderCardCardContainer
renderAudioAudioContainer
renderMediaMediaContainer

Change import of default styles

Until now, it was possible to import two stylesheets as follows:

import 'stream-chat-react/dist/css/v1/index.css';

Or

import 'stream-chat-react/dist/css/v2/index.css';

The legacy stylesheet has been removed from the SDK bundle, and therefore it is only possible to import one stylesheet from now on:

import 'stream-chat-react/dist/css/v2/index.css';

Action required
Make sure you are importing the default styles correctly as import 'stream-chat-react/dist/css/v2/index.css';

Removal of legacy styles

With the version 10 of stream-chat-react new stylesheet has been introduced. The stylesheet used previously became a legacy stylesheet. Legacy stylesheet had often times CSS classes and SDK components, that were not supported with the new stylesheet. Now, the legacy stylesheet and corresponding CSS classes and SDK component are being removed.

These changes will impact you only if you have imported the CSS as one of the following (you have used the legacy styles):

import 'stream-chat-react/css/index.css';
import '@stream-io/stream-chat-css/dist/css/index.css';

Removal of themeVersion from ChatContext

Supporting two stylesheet lead to introduction of a flag themeVersion into the ChatContext. This flag is no more necessary and has been removed from the context value.

Action required
Make sure you are not using themeVersion in your custom components.

With legacy stylesheet we have removed legacy approach to applying styles via component props. Two Chat component props were removed as a consequence:

  • customStyles
  • darkMode

Also associated parts of code were removed:

  • Theme type
  • useCustomStyles hook

Action required
1. The styles applied through customStyles should be applied through custom CSS.
2. Theme (not only dark theme) can be through Chat prop theme instead of darkMode

Removal from ComponentContext

  • AutocompleteSuggestionHeader - the up-to-date SDK markup does not count with a header in the ChatAutoComplete suggestion list

Action required
Make sure you are passing these custom components to the Channel component.

Removal of legacy components

The following components are not available anymore as they were related to legacy stylesheet and are not used by the latest SDK components.

Action required
1. Remove imports of these components from stream-chat-react in your custom components.
2. If importing SendIconV2 rename it to SendIcon.
3. Remove the listed classes if used in your CSS.

ComponentDetailsRemoved CSS classes
ChatDownused to be rendered as the default for LoadingErrorIndicator by ChannelListMessenger (the default ChannelList UI component). The default is now a null component (renders null)str-chat__down and str-chat__down-main
DefaultSuggestionListHeaderrendered only with legacy stylesheet in the ChatAutoComplete. As a consequence the AutocompleteSuggestionHeader prop has been removed from Channel props
Icons rendered Message component when legacy styles appliedReplyIcon, DeliveredCheckIcon, ErrorIcon
Icons rendered MessageInput component when legacy styles appliedEmojiIconLarge, EmojiIconSmall, FileUploadIcon, FileUploadIconFlat, SendIconV1 (SendIconV2 renamed to SendIcon)
MessageInputSmallUsed to be rendered in Thread, but was deprecated since v10 and replaced by MessageInputFlatall the classes starting with str-chat__small-message-input
UploadsPreviewUsed to be rendered in MessageInput but was deprecated since v10 and replaced with AttachmentPreviewList
FilePreviewer was rendered by UploadsPreviewUsed by component removed from the SDK
ImagePreviewer was rendered by UploadsPreviewUsed by component removed from the SDK
AttachmentIconNot used by the SDK
PictureIconNot used by the SDK
FileUploadButtonNot used by the SDK
ImageUploadButtonNot used by the SDK
ThumbnailPlaceholderNot used by the SDK
ThumbnailNot used by the SDK

Removal of legacy attachment file icons

The FileIcon component does not accept argument version anymore. This parameter used to determine the file icon set. There were two sets - version '1' and '2'. The icons of version '1' have been rendered with legacy stylesheets in the SDK components. The icons displayed under the version '1' have been removed now.

Action required
Remove prop version if the FileIcon is used in your custom components.

Removal of legacy CSS classes

We have removed classes that were used in the legacy CSS stylesheet only and thus are redundant. We recommend to use classes that were already available previously and are used by the SDK stylesheet:

Action required
Replace the removed classes with their alternatives in the custom CSS.

ComponentClass removedClass to be used instead
MediaContainerstr-chat__attachment-mediastr-chat__attachment
suggestion list in ReactTextAreaAutocompleterta__autocompletestr-chat__suggestion-list-container
Avatar root <div/>str-chat__avatar--circle, str-chat__avatar--square, str-chat__avatar--roundedstr-chat__avatar possibly combined with custom class
Avatar element <img/>str-chat__avatar-image--loaded
Channel root <div/>str-chat-channelstr-chat__channel
ChannelHeader root <div/>str-chat__header-livestreamstr-chat__channel-header
ChannelHeader root <div/> childrenstr-chat__header-livestream-leftstr-chat__channel-header-end
ChannelHeader root <div/> childrenstr-chat__header-livestream-left--titlestr-chat__channel-header-title
ChannelHeader root <div/> childrenstr-chat__header-livestream-left--subtitlestr-chat__channel-header-subtitle
ChannelHeader root <div/> childrenstr-chat__header-livestream-left--membersstr-chat__channel-header-info
ChannelList root <div/>str-chat-channel-liststr-chat__channel-list
ChannelPreviewMessenger root <div/> childrenstr-chat__channel-preview-messenger--rightstr-chat__channel-preview-end
SearchResults root <div/> childrenstr-chat__channel-search-containerstr-chat__channel-search-result-list
SuggestionList (rendered by ChatAutoComplete) container <div/>str-chat__emojisearchstr-chat__suggestion-list-container
SuggestionList (rendered by ChatAutoComplete) root <div/>str-chat__emojisearch__liststr-chat__suggestion-list
SuggestionListItem (rendered by SuggestionList) root <div/>str-chat__emojisearch__itemstr-chat__suggestion-list-item
EmojiPicker root <div/>str-chat__emojiselect-wrapper (only applied with legacy styles)str-chat__message-textarea-emoji-picker
EmojiPicker buttonstr-chat__input-flat-emojiselect (only applied with legacy styles)str-chat__emoji-picker-button
Emoji (rendered by Message)inline-text-emojithe <p/> element has been removed, no substitute class
MessageRepliesCountButton (rendered by Message) root <div/>str-chat__message-simple-reply-buttonstr-chat__message-replies-count-button-wrapper
Message wrapper <div/> around MessageStatus & MessageTimestampstr-chat__message-data, str-chat__message-simple-datastr-chat__message-metadata
QuotedMessage root <div/>quoted-messagestr-chat__quoted-message-preview
QuotedMessage bubblequoted-message-innerstr-chat__quoted-message-bubble
EditMessageFormstr-chat__edit-message-form-optionsno alternative
EditMessageFormstr-chat__fileupload-wrapperno alternative
EditMessageFormstr-chat__input-fileuploadno alternative
MessageInputFlat root <div/>all classes starting with str-chat__input-flatsee the current implementation of MessageInputFlat
QuotedMessagePreviewHeader (rendered by QuotedMessagePreviewHeader) root <div/>quoted-message-preview-headerstr-chat__quoted-message-preview-header
QuotedMessagePreviewHeader (rendered by QuotedMessagePreviewHeader) child <button/>str-chat__square-buttonstr-chat__quoted-message-remove
QuotedMessagePreview root <div/>quoted-message-previewno alternative
QuotedMessagePreviewquoted-message-preview-contentstr-chat__quoted-message-preview
QuotedMessagePreviewquoted-message-preview-content-innerstr-chat__quoted-message-bubble
MessageListstr-chat__thread--fullno alternative
InfiniteScroll rendered by MessageListstr-chat__reverse-infinite-scrollstr-chat__message-list-scroll
ScrollToBottomButtonstr-chat__message-notification-rightstr-chat__message-notification-scroll-to-latest
ScrollToBottomButtonstr-chat__message-notification-scroll-to-latest-unread-countstr-chat__jump-to-latest-unread-count
ReactionsListModalemojistr-chat__message-reaction-emoji or str-chat__message-reaction-emoji--with-fallback
SimpleReactionListstr-chat__simple-reactions-list-tooltipno alternative - markup removal
Threadstr-chat__list--threadstr-chat__thread-list
ThreadHeaderstr-chat__square-buttonstr-chat__close-thread-button
TypingIndicatorstr-chat__typing-indicator__avatarsno alternative - markup removal

Added classes

Migration to non-legacy styles leads to rendering of markup with the following classes:

Action required
Verify your app layout is not broken and adjust the CSS if necessary.

ClassDetails
str-chat__main-panel-innerA <div/> with this class wraps MessageList and VirtualizedMessageList

Removed types

Action required
Import type alternatives if necessary.

Removed typeDetailsTo be used instead
CustomMessageActionsTypeProps for component CustomMessageActionsList, that renders custom messages actions in MessageActionsBoxCustomMessageActionsListProps

TypingIndicator component without Avatars

The TypingIndicator component does not render avatars as it used to with legacy stylesheet. Therefore, its prop Avatar has been removed.

Action optional
Provide custom TypingIndicator through the Channel prop.

Updated browser target

Version 12 targets browsers that support ES2020. In particular, the code includes async functions, optional chaining (?.), and nullish coalescing (??). These features have been supported by all major desktop and mobile browsers for years, so it made sense for us to raise the baseline.

The following browsers support ES2020 and should be able to run the SDK as-is:

  • Chrome 80 and later
  • Safari 14.1 and later on desktops, 14.5 and later on iOS
  • Edge 80 and later
  • Firefox 80 and later

If you need to support older browsers, you should transpile your bundle using babel or a similar tool.

Action optional
If you’re targeting browsers that don’t support ES2020, use a transpilation tool like babel to process your bundle.

Browser bundle removed from the package

Prior to version 12, we included the browser bundle in the package, which could be added to the page using the <script> tag. We no longer ship the browser bundle.

Using the browser bundle was never recommended, and it was mostly for testing purposes. If you still want to quickly add the SDK using the <script> tag, you can use services such as https://esm.sh/ or https://www.unpkg.com/.

Installing the package from NPM and then bundling it with your application is still the best way to use the SDK.

© Getstream.io, Inc. All Rights Reserved.