Skip to main content
This guide builds a tabbed messaging UI with separate tabs for Chats, Calls, Users, and Groups plus a dedicated messages screen. It uses React Navigation with CometChat UI Kit components.

User Interface Overview

  • Tabs – switch between Chats, Calls, Users, and Groups.
  • Contextual list – conversation list, call logs, users, or groups per tab.
  • Message View – header + messages for the selected user/group.
  • Composer – send messages with attachments and reactions.
Initialize and log in with the Integration steps first.

Step-by-Step Guide

Step 1: Install navigation

npm install @react-navigation/native @react-navigation/stack @react-navigation/bottom-tabs react-native-safe-area-context react-native-screens

Step 2: Create the messages screen

Header + message list + composer with a back button that returns to tabs.
const MessagesRoot = ({ route, navigation }: any) => {
  const { user, group } = route.params || {};
  return (
    <View style={styles.flexOne}>
      <CometChatMessageHeader
        user={user}
        group={group}
        onBack={() => navigation.popToTop()}
        showBackButton
      />
      <View style={styles.flexOne}>
        <CometChatMessageList user={user} group={group} />
      </View>
      <CometChatMessageComposer
        user={user}
        group={group}
        keyboardAvoidingViewProps={Platform.OS === "ios" ? { behavior: "padding" } : {}}
      />
    </View>
  );
};

Step 3: Wire tabs to the stack

Use a bottom tab navigator for Chats, Calls, Users, Groups. Selecting a conversation pushes the Messages screen.
// src/examples/TabScreen.tsx
import React from "react";
import {
  NavigationContainer,
  DefaultTheme,
  useNavigation,
} from "@react-navigation/native";
import { createBottomTabNavigator } from "@react-navigation/bottom-tabs";
import { createStackNavigator, StackNavigationProp } from "@react-navigation/stack";
import {
  SafeAreaView,
  View,
  Platform,
  StyleSheet,
} from "react-native";
import {
  useTheme,
  CometChatConversations,
  CometChatGroups,
  CometChatCallLogs,
  CometChatUsers,
  CometChatUiKitConstants,
  CometChatMessageHeader,
  CometChatMessageList,
  CometChatMessageComposer,
} from "@cometchat/chat-uikit-react-native";
import { CometChat } from "@cometchat/chat-sdk-react-native";

const Stack = createStackNavigator();
const Tab = createBottomTabNavigator();

const Conversations: React.FC = () => {
  const navigation = useNavigation<StackNavigationProp<any>>();
  return (
    <CometChatConversations
      onItemPress={(conversation: CometChat.Conversation) => {
        const isUser =
          conversation.getConversationType() ===
          CometChatUiKitConstants.ConversationTypeConstants.user;

        navigation.navigate("MESSAGES_ROOT", isUser
          ? { user: conversation.getConversationWith() as CometChat.User }
          : { group: conversation.getConversationWith() as CometChat.Group }
        );
      }}
    />
  );
};

const Groups: React.FC = () => {
  const theme = useTheme();
  return (
    <SafeAreaView style={{ flex: 1, backgroundColor: theme.color.background1 }}>
      <CometChatGroups />
    </SafeAreaView>
  );
};

const Calls: React.FC = () => {
  const theme = useTheme();
  return (
    <SafeAreaView style={{ flex: 1, backgroundColor: theme.color.background1 }}>
      <CometChatCallLogs />
    </SafeAreaView>
  );
};

const Users: React.FC = () => {
  const theme = useTheme();
  const usersRequestBuilder = new CometChat.UsersRequestBuilder().setLimit(30);
  return (
    <SafeAreaView style={{ flex: 1, backgroundColor: theme.color.background1 }}>
      <CometChatUsers usersRequestBuilder={usersRequestBuilder} />
    </SafeAreaView>
  );
};

const BottomTabNavigator = () => (
  <Tab.Navigator screenOptions={{ headerShown: false }}>
    <Tab.Screen name="Chats" component={Conversations} />
    <Tab.Screen name="Calls" component={Calls} />
    <Tab.Screen name="Users" component={Users} />
    <Tab.Screen name="Groups" component={Groups} />
  </Tab.Navigator>
);

const TabScreen = () => {
  const theme = useTheme();
  const NavigationTheme = {
    ...DefaultTheme,
    colors: { ...DefaultTheme.colors, background: theme.color.background1 as string },
  };

  return (
    <NavigationContainer theme={NavigationTheme}>
      <Stack.Navigator initialRouteName="BOTTOM_TAB_NAVIGATOR" screenOptions={{ headerShown: false }}>
        <Stack.Screen name="BOTTOM_TAB_NAVIGATOR" component={BottomTabNavigator} />
        <Stack.Screen name="MESSAGES_ROOT" component={MessagesRoot as any} />
      </Stack.Navigator>
    </NavigationContainer>
  );
};

const styles = StyleSheet.create({
  flexOne: { flex: 1 },
});

export default TabScreen;
Render <TabScreen /> after the user logs in (e.g., in App.tsx) to expose tabs + chat.

Run the app

npm run android
npm run ios

Tips

  • The Chats tab passes either { user } or { group } into the Messages stack screen.
  • Use CometChatMessageHeader’s back button to return to tabs; add BackHandler if you want to handle Android hardware back.
  • Customize icons, colors, and typography via the ThemeProvider and useTheme.