<Channel MessageStatus={() => null}>
<MessageList />
</Channel>Message Status Indicators
The Stream Chat SDK for React Native provides a built-in way to display message status indicators to users. This feature enhances user experience by allowing users to see the status of the messages they are sending.
Message status indicators
In this cookbook, we will show you how to use the built-in message status indicators to display the status of the messages they are sending.
Status indicators states
The possible states of the status indicators are:
- sending: The message is pending to be sent to the server. It shows a timer icon.
- received: The message has been received by the server successfully. It is shown as a gray checkmark.
- delivered: The message has been delivered to at least one of the channel members devices. It is shown as double gray checkmark.
- read: The message has been read by at least one of the channel members. It is shown as double blue checkmark.
The delivered state is only available since version 8.8.0 and it needs to be enabled in the Dashboard for each channel type by enabling the Delivery Events flag/switch.
The read_events flag needs to be enabled in the Dashboard for each channel type by enabling the Read Events flag/switch.
| Pending | Sent | Delivered | Read | Read by many |
|---|---|---|---|---|
![]() | ![]() | ![]() | ![]() | ![]() |
Basic Customization
Hide status indicators
In case your app does not need to show the status indicators, you can hide them by overriding the MessageStatus component and passing it to the MessageStatus prop of the Channel component.
Show all read and delivered members

In this example, we will show you how to create a custom bottom sheet that shows the members that have read the message and the ones that were delivered but not read yet.
- First, create the bottom sheet component that will be used to show the members that have read the message and the ones that were delivered but not read yet.
import React, { useMemo } from "react";
import BottomSheet, { BottomSheetFlatList } from "@gorhom/bottom-sheet";
import { BottomSheetView } from "@gorhom/bottom-sheet";
import {
Avatar,
useChatContext,
useMessageDeliveredData,
useMessageReadData,
useTheme,
} from "stream-chat-react-native";
import { LocalMessage, UserResponse } from "stream-chat";
import { StyleSheet, Text, View } from "react-native";
const renderUserItem = ({ item }: { item: UserResponse }) => (
<View style={styles.userItem}>
<Avatar image={item.image} name={item.name ?? item.id} size={32} />
<Text style={styles.userName}>{item.name ?? item.id}</Text>
</View>
);
const renderEmptyText = ({ text }: { text: string }) => (
<Text style={styles.emptyText}>{text}</Text>
);
export const MessageInfoBottomSheet = ({
message,
ref,
}: {
message?: LocalMessage;
ref: React.RefObject<BottomSheet | null>;
}) => {
const {
theme: { colors },
} = useTheme();
const { client } = useChatContext();
const deliveredStatus = useMessageDeliveredData({ message });
const readStatus = useMessageReadData({ message });
const otherDeliveredToUsers = useMemo(() => {
return deliveredStatus.filter(
(user: UserResponse) => user.id !== client?.user?.id,
);
}, [deliveredStatus, client?.user?.id]);
const otherReadUsers = useMemo(() => {
return readStatus.filter(
(user: UserResponse) => user.id !== client?.user?.id,
);
}, [readStatus, client?.user?.id]);
return (
<BottomSheet enablePanDownToClose ref={ref} index={-1} snapPoints={["50%"]}>
<BottomSheetView
style={[styles.container, { backgroundColor: colors.white_smoke }]}
>
<Text style={styles.title}>Read</Text>
<BottomSheetFlatList
data={otherReadUsers}
renderItem={renderUserItem}
keyExtractor={(item) => item.id}
style={styles.flatList}
ListEmptyComponent={renderEmptyText({
text: "No one has read this message.",
})}
/>
<Text style={styles.title}>Delivered</Text>
<BottomSheetFlatList
data={otherDeliveredToUsers}
renderItem={renderUserItem}
keyExtractor={(item) => item.id}
style={styles.flatList}
ListEmptyComponent={renderEmptyText({
text: "The message was not delivered to anyone.",
})}
/>
</BottomSheetView>
</BottomSheet>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
padding: 24,
justifyContent: "center",
height: "100%",
},
title: {
fontSize: 16,
fontWeight: "bold",
marginVertical: 8,
},
flatList: {
borderRadius: 16,
},
userItem: {
flexDirection: "row",
alignItems: "center",
padding: 8,
backgroundColor: "white",
},
userName: {
fontSize: 16,
fontWeight: "bold",
marginLeft: 16,
},
emptyText: {
fontSize: 16,
marginVertical: 16,
textAlign: "center",
},
});- Then, you can open this bottom sheet by a custom message action that can be added as per the guide Custom Message Actions.
Mark as Delivered on Background push notification on Android
In this example, we will show you how to mark a message as delivered on background push notification on Android.
Using the setBackgroundMessageHandler method, you can mark a message as delivered on background push notification on Android.
An example of the above can be found below:
import {
FirebaseMessagingTypes,
setBackgroundMessageHandler,
} from '@react-native-firebase/messaging';
const displayNotification = async (
remoteMessage: FirebaseMessagingTypes.RemoteMessage,
channelId: string,
) => {
const { stream, ...rest } = remoteMessage.data ?? {};
const data = {
...rest,
...((stream as unknown as Record<string, string> | undefined) ?? {}), // extract and merge stream object if present
};
if (data.body && data.title) {
await notifee.displayNotification({
android: {
channelId,
pressAction: {
id: 'default',
},
},
body: data.body as string,
title: data.title as string,
data,
});
}
};
setBackgroundMessageHandler(messaging, async (remoteMessage) => {
try {
const loginConfig = // get the login config from the storage
if (!loginConfig) {
return;
}
const chatClient = StreamChat.getInstance(loginConfig.apiKey);
await chatClient._setToken(
{ id: loginConfig.userId },
loginConfig.userToken,
);
const notification = remoteMessage.data;
const deliverMessageConfirmation = [
{
cid: notification?.cid,
id: notification?.id,
},
];
await chatClient?.markChannelsDelivered({
latest_delivered_messages:
deliverMessageConfirmation as DeliveredMessageConfirmation[],
});
// create the android channel to send the notification to
const channelId = await notifee.createChannel({
id: "chat-messages",
name: "Chat Messages",
});
// display the notification
await displayNotification(remoteMessage, channelId);
} catch (error) {
console.error(error);
}
});Now, import the bootstrapBackgroundMessageHandler.ts file in the index.ts on the top of the file before the App component.
import "./bootstrapBackgroundMessageHandler";Now, you can test the above by sending a push notification to the app.




