Skip to main content
{
  "package": "@cometchat/chat-uikit-react",
  "conversationEvents": ["ccConversationDeleted", "ccUpdateConversation"],
  "userEvents": ["ccUserBlocked", "ccUserUnblocked"],
  "groupEvents": ["ccGroupCreated", "ccGroupDeleted", "ccGroupLeft", "ccGroupMemberScopeChanged", "ccGroupMemberKicked", "ccGroupMemberBanned", "ccGroupMemberUnbanned", "ccGroupMemberJoined", "ccGroupMemberAdded", "ccOwnershipChanged"],
  "messageEvents": ["ccMessageSent", "ccMessageEdited", "ccReplyToMessage", "ccMessageDeleted", "ccMessageRead", "ccLiveReaction"],
  "callEvents": ["ccOutgoingCall", "ccCallAccepted", "ccCallRejected", "ccCallEnded"],
  "uiEvents": ["ccActiveChatChanged"],
  "purpose": "Decoupled communication between UI Kit components"
}

Overview

Events provide decoupled communication between UI Kit components. Components emit events in response to user interactions or state changes, allowing other parts of your application to react without direct component references. Time estimate: 10 minutes
Difficulty: Intermediate

Prerequisites

Steps

Step 1: Import event classes

import {
  CometChatConversationEvents,
  CometChatUserEvents,
  CometChatGroupEvents,
  CometChatMessageEvents,
  CometChatCallEvents,
  CometChatUIEvents,
} from "@cometchat/chat-uikit-react";

Step 2: Subscribe to message events

Listen for sent, edited, and deleted messages:
import { useEffect } from "react";
import { CometChatMessageEvents } from "@cometchat/chat-uikit-react";

function useMessageEvents() {
  useEffect(() => {
    const sentSub = CometChatMessageEvents.ccMessageSent.subscribe((data) => {
      console.log("Message sent:", data.message.getText());
    });

    const editedSub = CometChatMessageEvents.ccMessageEdited.subscribe((data) => {
      console.log("Message edited:", data.message.getId());
    });

    const deletedSub = CometChatMessageEvents.ccMessageDeleted.subscribe((data) => {
      console.log("Message deleted:", data.message.getId());
    });

    // Cleanup subscriptions
    return () => {
      sentSub?.unsubscribe();
      editedSub?.unsubscribe();
      deletedSub?.unsubscribe();
    };
  }, []);
}

Step 3: Subscribe to group events

Track group membership changes:
import { useEffect } from "react";
import { CometChatGroupEvents } from "@cometchat/chat-uikit-react";

function useGroupEvents() {
  useEffect(() => {
    const kickedSub = CometChatGroupEvents.ccGroupMemberKicked.subscribe(
      (item) => {
        console.log("Member kicked:", item.kickedUser.getName());
        console.log("From group:", item.kickedFrom.getName());
      }
    );

    const scopeSub = CometChatGroupEvents.ccGroupMemberScopeChanged.subscribe(
      (item) => {
        console.log("Scope changed:", item.updatedUser.getName());
        console.log("New scope:", item.scopeChangedTo);
      }
    );

    const addedSub = CometChatGroupEvents.ccGroupMemberAdded.subscribe(
      (item) => {
        console.log("Members added:", item.usersAdded.length);
      }
    );

    return () => {
      kickedSub?.unsubscribe();
      scopeSub?.unsubscribe();
      addedSub?.unsubscribe();
    };
  }, []);
}

Step 4: Subscribe to conversation events

React to conversation updates:
import { useEffect } from "react";
import { CometChatConversationEvents } from "@cometchat/chat-uikit-react";

function useConversationEvents() {
  useEffect(() => {
    const deletedSub = CometChatConversationEvents.ccConversationDeleted.subscribe(
      (conversation) => {
        console.log("Conversation deleted:", conversation.getConversationId());
      }
    );

    const updateSub = CometChatConversationEvents.ccUpdateConversation.subscribe(
      (conversation) => {
        console.log("Conversation updated:", conversation.getConversationId());
      }
    );

    return () => {
      deletedSub?.unsubscribe();
      updateSub?.unsubscribe();
    };
  }, []);
}

Step 5: Subscribe to call events

Handle call state changes:
import { useEffect } from "react";
import { CometChatCallEvents } from "@cometchat/chat-uikit-react";

function useCallEvents() {
  useEffect(() => {
    const outgoingSub = CometChatCallEvents.ccOutgoingCall.subscribe((call) => {
      console.log("Outgoing call to:", call.getReceiverUid());
    });

    const acceptedSub = CometChatCallEvents.ccCallAccepted.subscribe((call) => {
      console.log("Call accepted:", call.getSessionId());
    });

    const rejectedSub = CometChatCallEvents.ccCallRejected.subscribe((call) => {
      console.log("Call rejected");
    });

    const endedSub = CometChatCallEvents.ccCallEnded.subscribe((call) => {
      console.log("Call ended");
    });

    return () => {
      outgoingSub?.unsubscribe();
      acceptedSub?.unsubscribe();
      rejectedSub?.unsubscribe();
      endedSub?.unsubscribe();
    };
  }, []);
}

Step 6: Track active chat changes

Know when the user switches conversations:
import { useEffect, useState } from "react";
import { CometChatUIEvents } from "@cometchat/chat-uikit-react";
import { CometChat } from "@cometchat/chat-sdk-javascript";

function useActiveChat() {
  const [activeChat, setActiveChat] = useState<{
    user?: CometChat.User;
    group?: CometChat.Group;
  }>({});

  useEffect(() => {
    const sub = CometChatUIEvents.ccActiveChatChanged.subscribe((data) => {
      setActiveChat({
        user: data.user,
        group: data.group,
      });
    });

    return () => sub?.unsubscribe();
  }, []);

  return activeChat;
}

Complete Example

import { useEffect, useState } from "react";
import {
  CometChatConversationEvents,
  CometChatGroupEvents,
  CometChatMessageEvents,
  CometChatCallEvents,
  CometChatUIEvents,
} from "@cometchat/chat-uikit-react";

interface EventLog {
  type: string;
  message: string;
  timestamp: Date;
}

function EventMonitor() {
  const [logs, setLogs] = useState<EventLog[]>([]);

  const addLog = (type: string, message: string) => {
    setLogs((prev) => [
      { type, message, timestamp: new Date() },
      ...prev.slice(0, 49), // Keep last 50 logs
    ]);
  };

  useEffect(() => {
    // Message events
    const msgSent = CometChatMessageEvents.ccMessageSent.subscribe((data) => {
      addLog("message", `Sent: ${data.message.getId()}`);
    });

    const msgDeleted = CometChatMessageEvents.ccMessageDeleted.subscribe((data) => {
      addLog("message", `Deleted: ${data.message.getId()}`);
    });

    // Group events
    const memberKicked = CometChatGroupEvents.ccGroupMemberKicked.subscribe((data) => {
      addLog("group", `Kicked: ${data.kickedUser.getName()}`);
    });

    const memberAdded = CometChatGroupEvents.ccGroupMemberAdded.subscribe((data) => {
      addLog("group", `Added ${data.usersAdded.length} members`);
    });

    // Conversation events
    const convDeleted = CometChatConversationEvents.ccConversationDeleted.subscribe((conv) => {
      addLog("conversation", `Deleted: ${conv.getConversationId()}`);
    });

    // Call events
    const callEnded = CometChatCallEvents.ccCallEnded.subscribe(() => {
      addLog("call", "Call ended");
    });

    // UI events
    const chatChanged = CometChatUIEvents.ccActiveChatChanged.subscribe((data) => {
      const name = data.user?.getName() || data.group?.getName() || "Unknown";
      addLog("ui", `Active chat: ${name}`);
    });

    return () => {
      msgSent?.unsubscribe();
      msgDeleted?.unsubscribe();
      memberKicked?.unsubscribe();
      memberAdded?.unsubscribe();
      convDeleted?.unsubscribe();
      callEnded?.unsubscribe();
      chatChanged?.unsubscribe();
    };
  }, []);

  return (
    <div style={{ padding: 16, maxHeight: 400, overflow: "auto" }}>
      <h3>Event Log</h3>
      {logs.map((log, i) => (
        <div key={i} style={{ fontSize: 12, marginBottom: 4 }}>
          <span style={{ color: "#666" }}>
            {log.timestamp.toLocaleTimeString()}
          </span>{" "}
          <span style={{ fontWeight: 600 }}>[{log.type}]</span> {log.message}
        </div>
      ))}
    </div>
  );
}

export default EventMonitor;

Event Reference

Conversation Events

EventDescription
ccConversationDeletedUser deleted a conversation
ccUpdateConversationConversation was updated

User Events

EventDescription
ccUserBlockedUser blocked another user
ccUserUnblockedUser unblocked another user

Group Events

EventDescription
ccGroupCreatedGroup was created
ccGroupDeletedGroup was deleted
ccGroupLeftUser left a group
ccGroupMemberScopeChangedMember’s scope was changed
ccGroupMemberKickedMember was kicked
ccGroupMemberBannedMember was banned
ccGroupMemberUnbannedMember was unbanned
ccGroupMemberJoinedUser joined a group
ccGroupMemberAddedMembers were added
ccOwnershipChangedGroup ownership transferred

Message Events

EventDescription
ccMessageSentMessage was sent
ccMessageEditedMessage was edited
ccReplyToMessageUser replied to a message
ccMessageDeletedMessage was deleted
ccMessageReadMessage was read
ccLiveReactionLive reaction was sent

Call Events

EventDescription
ccOutgoingCallOutgoing call initiated
ccCallAcceptedCall was accepted
ccCallRejectedCall was rejected
ccCallEndedCall ended

Common Issues

In React 18 StrictMode, useEffect runs twice on mount in development. Always return a cleanup function to unsubscribe and avoid duplicate event handling.
IssueSolution
Events firing twiceAdd cleanup function in useEffect return
Missing eventsVerify component is mounted and subscribed
Memory leaksAlways unsubscribe in cleanup

Next Steps