Skip to main content

Documentation Index

Fetch the complete documentation index at: https://cometchat-22654f5b-react-uikit-v7.mintlify.app/llms.txt

Use this file to discover all available pages before exploring further.

Goal

By the end of this guide you will have a chat interface where users can initiate new one-on-one conversations by selecting from a user list, or start group chats by selecting from available groups — then immediately begin messaging.

Prerequisites

Components Used

Component / APIPurpose
CometChatUsersLists available users for 1:1 chat selection
CometChatGroupsLists available groups for group chat selection
CometChatConversationsShows existing conversations
CometChatMessageHeaderDisplays selected user/group info
CometChatMessageListRenders conversation messages
CometChatMessageComposerText input for the conversation
CometChat.joinGroup()SDK method to join a group

Step 1: Set up the app shell

Wrap your application in CometChatProvider and create a layout that will hold the conversation area and a trigger for starting new chats.
App.tsx
import { useState } from "react";
import { CometChat } from "@cometchat/chat-sdk-javascript";
import { CometChatProvider } from "@cometchat/chat-uikit-react";
import "@cometchat/chat-uikit-react/styles";
import { NewChatApp } from "./NewChatApp";

function App() {
  return (
    <CometChatProvider
      appId="YOUR_APP_ID"
      region="YOUR_REGION"
      authKey="YOUR_AUTH_KEY"
    >
      <NewChatApp />
    </CometChatProvider>
  );
}

export default App;

Step 2: Add a “New Chat” trigger

Create a button that opens a selection panel. Use component state to toggle between the conversations view and the user/group selection view.
NewChatApp.tsx
import { useState } from "react";
import { CometChat } from "@cometchat/chat-sdk-javascript";
import { CometChatConversations } from "@cometchat/chat-uikit-react";

type ChatTarget =
  | { type: "user"; entity: CometChat.User }
  | { type: "group"; entity: CometChat.Group };

function NewChatApp() {
  const [showNewChat, setShowNewChat] = useState(false);
  const [activeChat, setActiveChat] = useState<ChatTarget | null>(null);

  return (
    <div style={{ display: "flex", height: "100vh" }}>
      <div style={{ width: "320px", borderRight: "1px solid #e0e0e0", display: "flex", flexDirection: "column" }}>
        <div style={{ padding: "8px", borderBottom: "1px solid #e0e0e0" }}>
          <button
            onClick={() => setShowNewChat(!showNewChat)}
            style={{ width: "100%", padding: "8px" }}
          >
            {showNewChat ? "Cancel" : "New Chat"}
          </button>
        </div>

        {showNewChat ? (
          <UserGroupSelector
            onSelectUser={(user) => {
              setActiveChat({ type: "user", entity: user });
              setShowNewChat(false);
            }}
            onSelectGroup={(group) => {
              setActiveChat({ type: "group", entity: group });
              setShowNewChat(false);
            }}
          />
        ) : (
          <div style={{ flex: 1, overflow: "hidden" }}>
            <CometChatConversations
              onItemClick={(conversation) => {
                const entity = conversation.getConversationWith();
                if (entity instanceof CometChat.User) {
                  setActiveChat({ type: "user", entity });
                } else if (entity instanceof CometChat.Group) {
                  setActiveChat({ type: "group", entity });
                }
              }}
            />
          </div>
        )}
      </div>

      <div style={{ flex: 1 }}>
        {activeChat ? (
          <ChatView target={activeChat} />
        ) : (
          <div style={{ display: "flex", alignItems: "center", justifyContent: "center", height: "100%" }}>
            <p>Select a conversation or start a new chat</p>
          </div>
        )}
      </div>
    </div>
  );
}

Step 3: Build the user/group selector

Use CometChatUsers and CometChatGroups to let the user pick a chat target. Add tabs to switch between users and groups.
UserGroupSelector.tsx
import { useState } from "react";
import { CometChat } from "@cometchat/chat-sdk-javascript";
import { CometChatUsers, CometChatGroups } from "@cometchat/chat-uikit-react";

function UserGroupSelector({
  onSelectUser,
  onSelectGroup,
}: {
  onSelectUser: (user: CometChat.User) => void;
  onSelectGroup: (group: CometChat.Group) => void;
}) {
  const [tab, setTab] = useState<"users" | "groups">("users");

  return (
    <div style={{ display: "flex", flexDirection: "column", flex: 1, overflow: "hidden" }}>
      <div style={{ display: "flex", borderBottom: "1px solid #e0e0e0" }}>
        <button
          onClick={() => setTab("users")}
          style={{
            flex: 1,
            padding: "8px",
            fontWeight: tab === "users" ? "bold" : "normal",
          }}
        >
          Users
        </button>
        <button
          onClick={() => setTab("groups")}
          style={{
            flex: 1,
            padding: "8px",
            fontWeight: tab === "groups" ? "bold" : "normal",
          }}
        >
          Groups
        </button>
      </div>

      <div style={{ flex: 1, overflow: "hidden" }}>
        {tab === "users" ? (
          <CometChatUsers onItemClick={onSelectUser} />
        ) : (
          <CometChatGroups onItemClick={onSelectGroup} />
        )}
      </div>
    </div>
  );
}

Step 4: Start a one-on-one conversation

When a user is selected from the list, pass the CometChat.User object to CometChatMessageList and CometChatMessageComposer. The SDK automatically creates the conversation when the first message is sent — no explicit creation step is needed.
ChatView.tsx
import { CometChat } from "@cometchat/chat-sdk-javascript";
import {
  CometChatMessageList,
  CometChatMessageComposer,
  CometChatMessageHeader,
} from "@cometchat/chat-uikit-react";

type ChatTarget =
  | { type: "user"; entity: CometChat.User }
  | { type: "group"; entity: CometChat.Group };

function ChatView({ target }: { target: ChatTarget }) {
  const userProp = target.type === "user" ? target.entity : undefined;
  const groupProp = target.type === "group" ? target.entity : undefined;

  return (
    <div style={{ display: "flex", flexDirection: "column", height: "100%" }}>
      <CometChatMessageHeader user={userProp} group={groupProp} />

      <div style={{ flex: 1, overflow: "hidden" }}>
        <CometChatMessageList user={userProp} group={groupProp} />
      </div>

      <CometChatMessageComposer user={userProp} group={groupProp} />
    </div>
  );
}

Step 5: Start a group conversation

For groups, the flow is the same — select a group from CometChatGroups and pass the CometChat.Group object to the message components. If the user hasn’t joined the group yet, you can call CometChat.joinGroup() before opening the chat.
async function handleGroupSelect(group: CometChat.Group) {
  // For public groups, join if not already a member
  if (!group.getHasJoined()) {
    try {
      const joinedGroup = await CometChat.joinGroup(
        group.getGuid(),
        CometChat.GROUP_TYPE.PUBLIC
      );
      onSelectGroup(joinedGroup);
    } catch (error) {
      console.error("Failed to join group:", error);
    }
  } else {
    onSelectGroup(group);
  }
}

Step 6: Send the first message programmatically (optional)

If you want to send an initial message when starting a new chat (for example, an icebreaker), use the SDK directly after selecting a user.
async function sendFirstMessage(uid: string, text: string) {
  const receiverType = CometChat.RECEIVER_TYPE.USER;
  const textMessage = new CometChat.TextMessage(uid, text, receiverType);

  try {
    const sentMessage = await CometChat.sendMessage(textMessage);
    console.log("Message sent:", sentMessage.getId());
  } catch (error) {
    console.error("Failed to send message:", error);
  }
}

Complete Example

NewChatApp.tsx
import { useState } from "react";
import { CometChat } from "@cometchat/chat-sdk-javascript";
import {
  CometChatProvider,
  CometChatConversations,
  CometChatUsers,
  CometChatGroups,
  CometChatMessageList,
  CometChatMessageComposer,
  CometChatMessageHeader,
} from "@cometchat/chat-uikit-react";
import "@cometchat/chat-uikit-react/styles";

type ChatTarget =
  | { type: "user"; entity: CometChat.User }
  | { type: "group"; entity: CometChat.Group };

function UserGroupSelector({
  onSelectUser,
  onSelectGroup,
}: {
  onSelectUser: (user: CometChat.User) => void;
  onSelectGroup: (group: CometChat.Group) => void;
}) {
  const [tab, setTab] = useState<"users" | "groups">("users");

  async function handleGroupSelect(group: CometChat.Group) {
    if (!group.getHasJoined()) {
      try {
        const joinedGroup = await CometChat.joinGroup(
          group.getGuid(),
          CometChat.GROUP_TYPE.PUBLIC
        );
        onSelectGroup(joinedGroup);
      } catch (error) {
        console.error("Failed to join group:", error);
      }
    } else {
      onSelectGroup(group);
    }
  }

  return (
    <div style={{ display: "flex", flexDirection: "column", flex: 1, overflow: "hidden" }}>
      <div style={{ display: "flex", borderBottom: "1px solid #e0e0e0" }}>
        <button
          onClick={() => setTab("users")}
          style={{
            flex: 1,
            padding: "8px",
            fontWeight: tab === "users" ? "bold" : "normal",
          }}
        >
          Users
        </button>
        <button
          onClick={() => setTab("groups")}
          style={{
            flex: 1,
            padding: "8px",
            fontWeight: tab === "groups" ? "bold" : "normal",
          }}
        >
          Groups
        </button>
      </div>

      <div style={{ flex: 1, overflow: "hidden" }}>
        {tab === "users" ? (
          <CometChatUsers onItemClick={onSelectUser} />
        ) : (
          <CometChatGroups onItemClick={handleGroupSelect} />
        )}
      </div>
    </div>
  );
}

function ChatView({ target }: { target: ChatTarget }) {
  const userProp = target.type === "user" ? target.entity : undefined;
  const groupProp = target.type === "group" ? target.entity : undefined;

  return (
    <div style={{ display: "flex", flexDirection: "column", height: "100%" }}>
      <CometChatMessageHeader user={userProp} group={groupProp} />

      <div style={{ flex: 1, overflow: "hidden" }}>
        <CometChatMessageList user={userProp} group={groupProp} />
      </div>

      <CometChatMessageComposer user={userProp} group={groupProp} />
    </div>
  );
}

function NewChatApp() {
  const [showNewChat, setShowNewChat] = useState(false);
  const [activeChat, setActiveChat] = useState<ChatTarget | null>(null);

  return (
    <div style={{ display: "flex", height: "100vh" }}>
      <div style={{ width: "320px", borderRight: "1px solid #e0e0e0", display: "flex", flexDirection: "column" }}>
        <div style={{ padding: "8px", borderBottom: "1px solid #e0e0e0" }}>
          <button
            onClick={() => setShowNewChat(!showNewChat)}
            style={{ width: "100%", padding: "8px" }}
          >
            {showNewChat ? "Cancel" : "New Chat"}
          </button>
        </div>

        {showNewChat ? (
          <UserGroupSelector
            onSelectUser={(user) => {
              setActiveChat({ type: "user", entity: user });
              setShowNewChat(false);
            }}
            onSelectGroup={(group) => {
              setActiveChat({ type: "group", entity: group });
              setShowNewChat(false);
            }}
          />
        ) : (
          <div style={{ flex: 1, overflow: "hidden" }}>
            <CometChatConversations
              onItemClick={(conversation) => {
                const entity = conversation.getConversationWith();
                if (entity instanceof CometChat.User) {
                  setActiveChat({ type: "user", entity });
                } else if (entity instanceof CometChat.Group) {
                  setActiveChat({ type: "group", entity });
                }
              }}
            />
          </div>
        )}
      </div>

      <div style={{ flex: 1 }}>
        {activeChat ? (
          <ChatView target={activeChat} />
        ) : (
          <div style={{ display: "flex", alignItems: "center", justifyContent: "center", height: "100%" }}>
            <p>Select a conversation or start a new chat</p>
          </div>
        )}
      </div>
    </div>
  );
}

function App() {
  return (
    <CometChatProvider
      appId="YOUR_APP_ID"
      region="YOUR_REGION"
      authKey="YOUR_AUTH_KEY"
    >
      <NewChatApp />
    </CometChatProvider>
  );
}

export default App;

Next Steps