Skip to main content
FieldValue
Package@cometchat/chat-uikit-react-native
FrameworkExpo
ComponentsCometChatConversations, CometChatUsers, CometChatGroups, CometChatCallLogs, CometChatMessageHeader, CometChatMessageList, CometChatMessageComposer
LayoutTabbed navigation (Chats, Users, Groups, Calls) + message view
PrerequisiteComplete Expo Integration Steps 1–4 first
PatternFull-featured messaging app with multiple sections
This guide builds a tabbed messaging UI — Chats, Users, Groups, and Calls tabs with bottom navigation, plus a message view when an item is selected. Good for full-featured apps that need more than just conversations. This assumes you’ve already completed Expo Integration (project created, UI Kit installed, init + login working).

What You’re Building

Three sections working together:
  1. Tab bar — switches between Chats, Users, Groups, and Calls
  2. List screens — renders the list for the active tab
  3. Message view — header + messages + composer for the selected item

Prerequisites

Install React Navigation dependencies:
npx expo install @react-navigation/native @react-navigation/bottom-tabs @react-navigation/native-stack react-native-screens

Step 1 — Create the Tab Screens

Create individual screen components for each tab:
screens/ConversationsScreen.tsx
import React from "react";
import { View } from "react-native";
import { CometChat } from "@cometchat/chat-sdk-react-native";
import {
  CometChatConversations,
  CometChatUiKitConstants,
} from "@cometchat/chat-uikit-react-native";
import { NativeStackNavigationProp } from "@react-navigation/native-stack";

type Props = {
  navigation: NativeStackNavigationProp<any>;
};

export function ConversationsScreen({ navigation }: Props) {
  const handleItemPress = (conversation: CometChat.Conversation) => {
    const conversationType = conversation.getConversationType();

    if (conversationType === CometChatUiKitConstants.ConversationTypeConstants.user) {
      const user = conversation.getConversationWith() as CometChat.User;
      navigation.navigate("Messages", { user });
    } else {
      const group = conversation.getConversationWith() as CometChat.Group;
      navigation.navigate("Messages", { group });
    }
  };

  return (
    <View style={{ flex: 1 }}>
      <CometChatConversations onItemPress={handleItemPress} />
    </View>
  );
}
screens/UsersScreen.tsx
import React from "react";
import { View } from "react-native";
import { CometChat } from "@cometchat/chat-sdk-react-native";
import { CometChatUsers } from "@cometchat/chat-uikit-react-native";
import { NativeStackNavigationProp } from "@react-navigation/native-stack";

type Props = {
  navigation: NativeStackNavigationProp<any>;
};

export function UsersScreen({ navigation }: Props) {
  const handleItemPress = (user: CometChat.User) => {
    navigation.navigate("Messages", { user });
  };

  return (
    <View style={{ flex: 1 }}>
      <CometChatUsers onItemPress={handleItemPress} />
    </View>
  );
}
screens/GroupsScreen.tsx
import React from "react";
import { View } from "react-native";
import { CometChat } from "@cometchat/chat-sdk-react-native";
import { CometChatGroups } from "@cometchat/chat-uikit-react-native";
import { NativeStackNavigationProp } from "@react-navigation/native-stack";

type Props = {
  navigation: NativeStackNavigationProp<any>;
};

export function GroupsScreen({ navigation }: Props) {
  const handleItemPress = (group: CometChat.Group) => {
    navigation.navigate("Messages", { group });
  };

  return (
    <View style={{ flex: 1 }}>
      <CometChatGroups onItemPress={handleItemPress} />
    </View>
  );
}
screens/CallLogsScreen.tsx
import React from "react";
import { View } from "react-native";
import { CometChatCallLogs } from "@cometchat/chat-uikit-react-native";

export function CallLogsScreen() {
  return (
    <View style={{ flex: 1 }}>
      <CometChatCallLogs />
    </View>
  );
}

Step 2 — Create the Messages Screen

screens/MessagesScreen.tsx
import React from "react";
import { View } from "react-native";
import { CometChat } from "@cometchat/chat-sdk-react-native";
import {
  CometChatMessageHeader,
  CometChatMessageList,
  CometChatMessageComposer,
} from "@cometchat/chat-uikit-react-native";
import { RouteProp } from "@react-navigation/native";
import { NativeStackNavigationProp } from "@react-navigation/native-stack";

type MessagesRouteParams = {
  Messages: {
    user?: CometChat.User;
    group?: CometChat.Group;
  };
};

type Props = {
  route: RouteProp<MessagesRouteParams, "Messages">;
  navigation: NativeStackNavigationProp<any>;
};

export function MessagesScreen({ route, navigation }: Props) {
  const { user, group } = route.params;

  return (
    <View style={{ flex: 1 }}>
      <CometChatMessageHeader
        user={user}
        group={group}
        onBack={() => navigation.goBack()}
        showBackButton
      />
      <CometChatMessageList user={user} group={group} />
      <CometChatMessageComposer user={user} group={group} />
    </View>
  );
}

Step 3 — Set Up Navigation

App.tsx
import React, { useEffect, useState } from "react";
import { Image, StyleSheet } from "react-native";
import { NavigationContainer } from "@react-navigation/native";
import { createNativeStackNavigator } from "@react-navigation/native-stack";
import { createBottomTabNavigator } from "@react-navigation/bottom-tabs";
import { SafeAreaProvider } from "react-native-safe-area-context";
import { GestureHandlerRootView } from "react-native-gesture-handler";
import {
  CometChatUIKit,
  UIKitSettings,
  CometChatThemeProvider,
  CometChatI18nProvider,
} from "@cometchat/chat-uikit-react-native";
import { CometChat } from "@cometchat/chat-sdk-react-native";

import { ConversationsScreen } from "./screens/ConversationsScreen";
import { UsersScreen } from "./screens/UsersScreen";
import { GroupsScreen } from "./screens/GroupsScreen";
import { CallLogsScreen } from "./screens/CallLogsScreen";
import { MessagesScreen } from "./screens/MessagesScreen";

const APP_ID = "APP_ID";
const AUTH_KEY = "AUTH_KEY";
const REGION = "REGION";
const UID = "cometchat-uid-1";

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

function TabNavigator() {
  return (
    <Tab.Navigator
      screenOptions={{
        tabBarActiveTintColor: "#6851D6",
        tabBarInactiveTintColor: "#808080",
        headerShown: false,
        tabBarStyle: styles.tabBar,
      }}
    >
      <Tab.Screen
        name="Chats"
        component={ConversationsScreen}
        options={{
          tabBarIcon: ({ color }) => (
            <Image
              source={require("./assets/chats.png")}
              style={[styles.tabIcon, { tintColor: color }]}
            />
          ),
        }}
      />
      <Tab.Screen
        name="Users"
        component={UsersScreen}
        options={{
          tabBarIcon: ({ color }) => (
            <Image
              source={require("./assets/users.png")}
              style={[styles.tabIcon, { tintColor: color }]}
            />
          ),
        }}
      />
      <Tab.Screen
        name="Groups"
        component={GroupsScreen}
        options={{
          tabBarIcon: ({ color }) => (
            <Image
              source={require("./assets/groups.png")}
              style={[styles.tabIcon, { tintColor: color }]}
            />
          ),
        }}
      />
      <Tab.Screen
        name="Calls"
        component={CallLogsScreen}
        options={{
          tabBarIcon: ({ color }) => (
            <Image
              source={require("./assets/calls.png")}
              style={[styles.tabIcon, { tintColor: color }]}
            />
          ),
        }}
      />
    </Tab.Navigator>
  );
}

export default function App() {
  const [loggedIn, setLoggedIn] = useState(false);

  useEffect(() => {
    const init = async () => {
      const uiKitSettings: UIKitSettings = {
        appId: APP_ID,
        authKey: AUTH_KEY,
        region: REGION,
        subscriptionType: CometChat.AppSettings
          .SUBSCRIPTION_TYPE_ALL_USERS as UIKitSettings["subscriptionType"],
      };

      try {
        await CometChatUIKit.init(uiKitSettings);
        await CometChatUIKit.login({ uid: UID });
        setLoggedIn(true);
      } catch (err) {
        console.error("Init/login error:", err);
      }
    };

    init();
  }, []);

  if (!loggedIn) return null;

  return (
    <GestureHandlerRootView style={{ flex: 1 }}>
      <SafeAreaProvider>
        <CometChatI18nProvider>
          <CometChatThemeProvider>
            <NavigationContainer>
              <Stack.Navigator screenOptions={{ headerShown: false }}>
                <Stack.Screen name="Home" component={TabNavigator} />
                <Stack.Screen name="Messages" component={MessagesScreen} />
              </Stack.Navigator>
            </NavigationContainer>
          </CometChatThemeProvider>
        </CometChatI18nProvider>
      </SafeAreaProvider>
    </GestureHandlerRootView>
  );
}

const styles = StyleSheet.create({
  tabBar: {
    backgroundColor: "#FFFFFF",
    borderTopWidth: 1,
    borderTopColor: "#E8E8E8",
    paddingBottom: 5,
    paddingTop: 5,
    height: 60,
  },
  tabIcon: {
    width: 24,
    height: 24,
  },
});
Download tab icons from the CometChat UI Kit assets folder on GitHub and place them in your assets/ folder.

Step 4 — Run the Project

npx expo run:ios
You should see the tab bar at the bottom. Switch between Chats, Users, Groups, and Calls — tapping any item navigates to the message view.

Next Steps

Theming

Customize colors, fonts, and styles to match your brand

Components Overview

Browse all prebuilt UI components

Expo Integration

Back to the main setup guide

Core Features

Chat features included out of the box