<ThreadProvider thread={thread}>
<Thread />
</ThreadProvider>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.
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:
AttachmentDateSeparatorMessageMessageSystemreactionOptionsUnreadMessagesSeparator
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:
- The library
@breezystack/lamejshas to be installed as this is a peer dependency tostream-chat-react.
npm install @breezystack/lamejsyarn add @breezystack/lamejs- 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 ofReactionSelectorrepresented by another removed value -showDetailedReactionsshowDetailedReactions- flag used to decide, whether the reaction selector should be shown or notreactionSelectorRef- 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:
All the attachments except the link preview attachments (objects that contain
og_scrape_urlattribute) are now stored inattachmentsarray ofMessageInputContext. Array keeps order and the attachment type can be determined by theattachment.typeproperty.The previously removed “local” data is now stored on each attachment object under
localMetadatakey. This key is removed upon submission. EverylocalMetadataobject has to at least contain theidattribute that allows us to update or remove the given attachment from the state. The attachments that represent an uploaded file has to also include thelocalMetadata.filereference.Attachments representing uploaded files will be identified by the
fileattribute asattachment.localMetadata.file. Default attachment types recognized by the SDK are:
audiofileimagevideovoiceRecording
The attachment
typeis 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:We have removed the following API tied to uploads state from the MessageInput state
uploadFile-> from now on, useuploadAttachmentuploadImage-> from now on, useuploadAttachmentremoveFile-> from now on, useremoveAttachmentsremoveImage-> from now on, useremoveAttachments
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 vialinkPreviews(see the guide on how to uselinkPreviews).uploadAttachment- Uploads a single attachment. The provided attachment should contain alocalMetadataobject withfile(references aFileinstance to be uploaded) andidproperties.uploadNewFiles- Expects an array ofFileorBlobobjects, generates an array of well-formed attachments and uploads the files withuploadAttachmentfunctionupsertAttachments- Expects an array of attachment object where each of those should containlocalMetadata.id. Creates or updates the attachment attributes based on the given id in theattachmentsarray ofMessageInputContext.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):
fileOrderimageOrderfileUploadsimageUploadsuploadFileuploadImageremoveFileremoveImage
Date & time formatting
The components that display date and time are:
DateSeparator- separates message groups in message listsEventComponent- displays system messagesMessageTimestamp- 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:
Props
shapeandsizewere removed. Subsequently, the classstr-chat__avatar--${shape}was removed.Another class we removed is
str-chat__avatar-image--loadedthat was applied toimgelement in theAvatarcomponent.New prop
classNamehas been added toAvatar. Integrators can now optionally apply custom styles to custom classes.There have also been added new classes to
Avatarrootdivin different components:
| Component | Avatar root CSS class |
|---|---|
ChannelHeader | str-chat__avatar--channel-header |
ChannelPreviewMessenger | str-chat__avatar--channel-preview |
MessageStatus | str-chat__avatar--message-status |
ReactionsList | stream-chat__avatar--reaction |
QuotedMessage | str-chat__avatar--quoted-message-sender |
SearchResultItem | str-chat__avatar--channel-preview |
UserItem rendered by SuggestionListItem | str-chat__avatar--autocomplete-item |
- As a consequence of the
Avatarprops changes, theTypingIndicatorpropavatarSizehave 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:
- class
str-chat__main-panel--hideOnThreadwas replaced by classstr-chat__main-panel--thread-open - the class
str-chat__main-panel--thread-openis attached to the root<div/>always, when thread is open - the default value of
hideOnThreadprop wasfalse(Windowcontents 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 ruledisplay: nonetostr-chat__main-panel--thread-openclass
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 function | Component equivalent |
|---|---|
renderAttachmentWithinContainer | AttachmentWithinContainer |
renderAttachmentActions | AttachmentActionsContainer |
renderGallery | GalleryContainer |
renderImage | ImageContainer |
renderCard | CardContainer |
renderAudio | AudioContainer |
renderMedia | MediaContainer |
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.
Removal of styles related Chat props
With legacy stylesheet we have removed legacy approach to applying styles via component props. Two Chat component props were removed as a consequence:
customStylesdarkMode
Also associated parts of code were removed:
ThemetypeuseCustomStyleshook
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 theChatAutoCompletesuggestion 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.
| Component | Details | Removed CSS classes |
|---|---|---|
DefaultSuggestionListHeader | rendered 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 applied | ReplyIcon, DeliveredCheckIcon, ErrorIcon | |
Icons rendered MessageInput component when legacy styles applied | EmojiIconLarge, EmojiIconSmall, FileUploadIcon, FileUploadIconFlat, SendIconV1 (SendIconV2 renamed to SendIcon) | |
MessageInputSmall | Used to be rendered in Thread, but was deprecated since v10 and replaced by MessageInputFlat | all the classes starting with str-chat__small-message-input |
UploadsPreview | Used to be rendered in MessageInput but was deprecated since v10 and replaced with AttachmentPreviewList | |
FilePreviewer was rendered by UploadsPreview | Used by component removed from the SDK | |
ImagePreviewer was rendered by UploadsPreview | Used by component removed from the SDK | |
AttachmentIcon | Not used by the SDK | |
PictureIcon | Not used by the SDK | |
FileUploadButton | Not used by the SDK | |
ImageUploadButton | Not used by the SDK | |
ThumbnailPlaceholder | Not used by the SDK | |
Thumbnail | Not 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.
| Component | Class removed | Class to be used instead |
|---|---|---|
MediaContainer | str-chat__attachment-media | str-chat__attachment |
suggestion list in ReactTextAreaAutocomplete | rta__autocomplete | str-chat__suggestion-list-container |
Avatar root <div/> | str-chat__avatar--circle, str-chat__avatar--square, str-chat__avatar--rounded | str-chat__avatar possibly combined with custom class |
Avatar element <img/> | str-chat__avatar-image--loaded | |
Channel root <div/> | str-chat-channel | str-chat__channel |
ChannelHeader root <div/> | str-chat__header-livestream | str-chat__channel-header |
ChannelHeader root <div/> children | str-chat__header-livestream-left | str-chat__channel-header-end |
ChannelHeader root <div/> children | str-chat__header-livestream-left--title | str-chat__channel-header-title |
ChannelHeader root <div/> children | str-chat__header-livestream-left--subtitle | str-chat__channel-header-subtitle |
ChannelHeader root <div/> children | str-chat__header-livestream-left--members | str-chat__channel-header-info |
ChannelList root <div/> | str-chat-channel-list | str-chat__channel-list |
ChannelPreviewMessenger root <div/> children | str-chat__channel-preview-messenger--right | str-chat__channel-preview-end |
SearchResults root <div/> children | str-chat__channel-search-container | str-chat__channel-search-result-list |
SuggestionList (rendered by ChatAutoComplete) container <div/> | str-chat__emojisearch | str-chat__suggestion-list-container |
SuggestionList (rendered by ChatAutoComplete) root <div/> | str-chat__emojisearch__list | str-chat__suggestion-list |
SuggestionListItem (rendered by SuggestionList) root <div/> | str-chat__emojisearch__item | str-chat__suggestion-list-item |
EmojiPicker root <div/> | str-chat__emojiselect-wrapper (only applied with legacy styles) | str-chat__message-textarea-emoji-picker |
EmojiPicker button | str-chat__input-flat-emojiselect (only applied with legacy styles) | str-chat__emoji-picker-button |
Emoji (rendered by Message) | inline-text-emoji | the <p/> element has been removed, no substitute class |
MessageRepliesCountButton (rendered by Message) root <div/> | str-chat__message-simple-reply-button | str-chat__message-replies-count-button-wrapper |
Message wrapper <div/> around MessageStatus & MessageTimestamp | str-chat__message-data, str-chat__message-simple-data | str-chat__message-metadata |
QuotedMessage root <div/> | quoted-message | str-chat__quoted-message-preview |
QuotedMessage bubble | quoted-message-inner | str-chat__quoted-message-bubble |
EditMessageForm | str-chat__edit-message-form-options | no alternative |
EditMessageForm | str-chat__fileupload-wrapper | no alternative |
EditMessageForm | str-chat__input-fileupload | no alternative |
MessageInputFlat root <div/> | all classes starting with str-chat__input-flat | see the current implementation of MessageInputFlat |
QuotedMessagePreviewHeader (rendered by QuotedMessagePreviewHeader) root <div/> | quoted-message-preview-header | str-chat__quoted-message-preview-header |
QuotedMessagePreviewHeader (rendered by QuotedMessagePreviewHeader) child <button/> | str-chat__square-button | str-chat__quoted-message-remove |
QuotedMessagePreview root <div/> | quoted-message-preview | no alternative |
QuotedMessagePreview | quoted-message-preview-content | str-chat__quoted-message-preview |
QuotedMessagePreview | quoted-message-preview-content-inner | str-chat__quoted-message-bubble |
MessageList | str-chat__thread--full | no alternative |
InfiniteScroll rendered by MessageList | str-chat__reverse-infinite-scroll | str-chat__message-list-scroll |
ScrollToBottomButton | str-chat__message-notification-right | str-chat__message-notification-scroll-to-latest |
ScrollToBottomButton | str-chat__message-notification-scroll-to-latest-unread-count | str-chat__jump-to-latest-unread-count |
ReactionsListModal | emoji | str-chat__message-reaction-emoji or str-chat__message-reaction-emoji--with-fallback |
SimpleReactionList | str-chat__simple-reactions-list-tooltip | no alternative - markup removal |
Thread | str-chat__list--thread | str-chat__thread-list |
ThreadHeader | str-chat__square-button | str-chat__close-thread-button |
TypingIndicator | str-chat__typing-indicator__avatars | no 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.
| Class | Details |
|---|---|
str-chat__main-panel-inner | A <div/> with this class wraps MessageList and VirtualizedMessageList |
Removed types
Action required
Import type alternatives if necessary.
| Removed type | Details | To be used instead |
|---|---|---|
CustomMessageActionsType | Props for component CustomMessageActionsList, that renders custom messages actions in MessageActionsBox | CustomMessageActionsListProps |
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.
- Introducing Threads 2.0
- Introducing WithComponents & Dropping Defaults
- Dropped ComponentContext Defaults
- Audio recordings transcoding
- Unified dialog management
- EmojiPickerIcon extraction to emojis plugin
- Removal of duplicate uploads state in MessageInput
- Date & time formatting
- Avatar changes
- Removal of styling props
- Removal of deprecated components
- Change import of default styles
- Removal of legacy styles
- Updated browser target
- Browser bundle removed from the package