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

Reaction components

Reactions show in three places: on the message, as a list above or under the bubble; in the message menu, as a picker above the message; and in a bottom sheet that lists who reacted. Every component on this page is an override key of the same name. The ReactionListItemWrapper key has no effect; see ReactionListItemWrapper. Reactions covers the feature across the layers.

Best practices

  • Set the reactions on offer with supportedReactions on Channel or Thread. Every component here reads them from MessagesContext, and a reaction of a type not in the list doesn't show on messages.
  • Pick the layout with reactionListPosition and reactionListType on Channel before you replace a component.
  • Change what a tap on a reaction does with onPressMessage on Channel: the payload's emitter is reactionList and additionalInfo.reactionType the pressed type. Toggling a reaction with a tap shows it.
  • Change what picking a reaction does with selectReaction or handleReaction on Channel, not by replacing the picker.

Basic usage

This wrapper shows the reactions above the bubble as separate pills without counts:

src/ReactionListTopWithoutCounts.tsx
import {
  ReactionListTop,
  type ReactionListTopProps,
  WithComponents,
} from "stream-chat-react-native";

const ReactionListTopWithoutCounts = (props: ReactionListTopProps) => (
  <ReactionListTop {...props} showCount={false} type="segmented" />
);

const overrides = { ReactionListTop: ReactionListTopWithoutCounts };

export const MessagesWithPlainReactions = ({
  children,
}: {
  children: React.ReactNode;
}) => <WithComponents overrides={overrides}>{children}</WithComponents>;

Custom reactions changes the reactions on offer and their icons.

The reactions on a message

MessageItemView renders ReactionListTop above the bubble with reactionListPosition="top", the default, and ReactionListBottom under it with "bottom", passing reactionListType as type. Both render nothing while the message has no reaction of a supported type. A message's reactions come from MessageContext.reactions: one entry for each type, with its count and whether the user gave it, the oldest type first.

Pressing a reaction reports the reactionList emitter, and by default opens the reactions sheet with that type selected. Pressing the clustered list, or the "+N" pill, opens it with every type.

ReactionListTop

With type="clustered" it renders ReactionListClustered. With any other type, or none, it renders up to four ReactionListItem pills in a row, then a ReactionListCountItem with the number of other types. A prop set here is used when it's truthy; otherwise the context value is.

Prop Type Default Description
alignment Alignment from MessageContext Puts the list at the bubble's right or left edge.
hasReactions boolean from MessageContext Whether the message has reactions.
onLongPress (payload: PressableHandlerPayload) => void from MessageContext Called on a long press on a pill.
onPress (payload: MessagePressableHandlerPayload) => void from MessageContext Called on a press on a pill.
onPressIn ((payload: PressableHandlerPayload) => void) | null from MessageContext Called when a press on a pill starts.
preventPress boolean from MessageContext Turns off presses.
reactionListType "clustered" | "segmented" Not used. The list follows type.
reactions ReactionSummary[] from MessageContext The reactions to show.
showCount boolean true Shows each pill's count.
showReactionsOverlay (selectedReaction?: string) => void from MessageContext Opens the reactions sheet.
supportedReactions ReactionData[] from MessagesContext The reactions on offer, for the icons.
type "clustered" | "segmented" 'clustered' renders ReactionListClustered.

ReactionListBottom

With type="segmented" it renders a ReactionListItem pill for every type, five to a row, or six without counts. With any other type, or none, it renders ReactionListClustered. A prop set here is used when it's truthy; otherwise the context value is.

Prop Type Default Description
alignment Alignment from MessageContext Aligns the rows left or right.
hasReactions boolean from MessageContext Whether the message has reactions.
onLongPress (payload: PressableHandlerPayload) => void from MessageContext Called on a long press on a pill.
onPress (payload: MessagePressableHandlerPayload) => void from MessageContext Called on a press on a pill.
onPressIn ((payload: PressableHandlerPayload) => void) | null from MessageContext Called when a press on a pill starts.
preventPress boolean from MessageContext Turns off presses.
reactions ReactionSummary[] from MessageContext The reactions to show.
showCount boolean true Shows each pill's count.
showReactionsOverlay (selectedReaction?: string) => void from MessageContext Opens the reactions sheet.
supportedReactions ReactionData[] from MessagesContext The reactions on offer, for the icons.
type "clustered" | "segmented" 'segmented' renders a pill for each type.

ReactionListClustered

Renders the icons of up to four reaction types in one pill, followed by the number of other types when there are more. Pressing it reports the reactionList emitter, and by default opens the reactions sheet with every type.

Prop Type Default Description
accessibilityLabel string The pill's accessibility label.
containerStyle StyleProp<ViewStyle> Style of the pill.
hasReactions boolean from MessageContext Whether the message has reactions.
onPress (payload: MessagePressableHandlerPayload) => void from MessageContext Called on a press.
onPressIn ((payload: PressableHandlerPayload) => void) | null from MessageContext Called when a press starts.
preventPress boolean from MessageContext Turns off presses.
reactions ReactionSummary[] from MessageContext The reactions to show.
showReactionsOverlay (selectedReaction?: string) => void from MessageContext Opens the reactions sheet.
supportedReactions ReactionData[] from MessagesContext The reactions on offer, for the icons.

ReactionListItem

Renders one reaction type as a pill: its icon, or the Unknown icon when the type isn't in supportedReactions, and its count. A press or a long press reports the reactionList emitter with additionalInfo.reactionType, and by default opens the reactions sheet at that type.

Prop Type Default Description
onLongPress (payload: PressableHandlerPayload) => void Called on a long press.
onPress (payload: MessagePressableHandlerPayload) => void Called on a press.
onPressIn ((payload: PressableHandlerPayload) => void) | null Called when a press starts.
preventPress boolean Turns off presses.
reaction ReactionSummary required The reaction type, with its count.
selected boolean false Highlights the pill, and tells screen readers the user reacted. The lists pass the reaction's own.
showCount boolean true Shows the count.
showReactionsOverlay (selectedReaction?: string) => void Opens the reactions sheet.
supportedReactions ReactionData[] The reactions on offer, for the icon.

ReactionListItem reads nothing from context: the lists pass every prop.

ReactionListCountItem

Renders "+3", the number of reaction types ReactionListTop leaves out. It renders nothing for a count of 0. Pressing it opens the reactions sheet with every type.

Prop Type Default Description
count number required The number to show.
onLongPress (payload: PressableHandlerPayload) => void Called on a long press.
onPress (payload: MessagePressableHandlerPayload) => void Called on a press.
onPressIn ((payload: PressableHandlerPayload) => void) | null Called when a press starts.
preventPress boolean Turns off presses.
selected boolean Highlights the pill.
showReactionsOverlay (selectedReaction?: string) => void Opens the reactions sheet.

ReactionListItemWrapper

The Pressable pill the items and the clustered list render in. They import it directly, so the ReactionListItemWrapper override key has no effect; style the pill through theme.messageItemView.reactionListItemWrapper. It takes every Pressable prop, and:

Prop Type Default Description
selected boolean false Uses the selected background.
style StyleProp<ViewStyle> Style of the pill, applied after the SDK's.

The reaction picker

MessageReactionPicker renders above the message while the message menu is open: the reactions of supportedReactions with isMain, the ones the user gave highlighted, and a button that opens a sheet with the full emoji list. Picking a reaction closes the menu, then calls handleReaction. It renders nothing when the user can't send reactions.

Prop Type Default Description
dismissOverlay () => void required Closes the message menu.
handleReaction (reactionType: string) => Promise<void> Called with the picked type after the menu closes. Message passes the message's handleReaction when the user can send reactions.
supportedReactions ReactionData[] Not used. The picker reads them from MessagesContext.

The emoji sheet lists a fixed set of emojis, whatever supportedReactions holds.

The reactions sheet

MessageUserReactions renders in a bottom sheet, which showReactionsOverlay opens: the total count, a row of the message's reaction types with their counts, and the users who reacted, loaded page by page, newest first. Picking a type in the row filters the users. The + button at the start of the row shows the emoji list; picking an emoji calls the message's handleReaction and closes the sheet.

Prop Type Default Description
message LocalMessage The message whose reactions show. Message passes it; it isn't read from context.
reactions Reaction[] the reactions loaded from the server The users to list, in place of the loaded ones.
selectedReaction string The type selected when the sheet opens.
supportedReactions ReactionData[] from MessagesContext The reactions on offer. Types not in it don't show in the row.

MessageUserReactionsItem

Renders one user in the sheet, with the MessageUserReactionsAvatar override, the name, or "You" with "Tap to remove", and the reaction's icon. Pressing the user's own reaction removes it through handleReaction. It isn't exported; replace it with the MessageUserReactionsItem key.

Prop Type Default Description
reaction Reaction required The reaction: the user's id, name and image, and the type.
supportedReactions ReactionData[] required The reactions on offer, for the icon.

MessageUserReactionsAvatar

Renders the avatar of the user who reacted, or their initials.

Prop Type Default Description
reaction Reaction required The reaction, with the user's name and image.
size "sm" | "md" | "lg" | "xl" | "xs" | "2xl" 'lg' The avatar's size. MessageUserReactionsItem passes 'md'.
  • useMessageContext() returns the message's reactions, hasReactions, handleReaction, handleToggleReaction and showReactionsOverlay.
  • useMessagesContext() returns supportedReactions, reactionListPosition and reactionListType.
  • useFetchReactions({ message, reactionType, sort }) loads the users who reacted, as the sheet does. See Message hooks.