Quick Reference for AI Agents & Developers // Send a thread reply
const textMessage = new CometChat . TextMessage ( receiverID , "Reply text" , receiverType );
textMessage . setParentMessageId ( parentMessageId ); // Required for thread
await CometChat . sendMessage ( textMessage );
// Fetch thread messages
const messagesRequest = new CometChat . MessagesRequestBuilder ()
. setParentMessageId ( parentMessageId )
. setLimit ( 30 )
. build ();
const threadMessages = await messagesRequest . fetchPrevious ();
// Hide thread replies in main chat
const messagesRequest = new CometChat . MessagesRequestBuilder ()
. setGUID ( guid )
. hideReplies ( true )
. build ();
// Get reply count
const replyCount = message . getReplyCount ();
// Listen for thread messages
if ( message . getParentMessageId () === activeThreadId ) {
// This is a thread reply
}
Threaded messages are replies attached to a specific parent message. They help organize discussions by keeping related messages grouped together, especially useful in busy group conversations.
How Threads Work
┌─────────────────────────────────────┐
│ Parent Message (ID: 100) │
│ "What should we do for the launch?" │
└─────────────────────────────────────┘
│
├── Reply 1 (parentMessageId: 100)
│ "I think we should focus on social media"
│
├── Reply 2 (parentMessageId: 100)
│ "Agreed, let's create a content calendar"
│
└── Reply 3 (parentMessageId: 100)
"I'll draft some posts by Friday"
Send a Thread Reply
Set the parentMessageId to send a message as part of a thread:
Text Message
Media Message
TypeScript
Async/Await
const receiverID = "UID" ;
const parentMessageId = 100 ;
const textMessage = new CometChat . TextMessage (
receiverID ,
"This is a reply in the thread" ,
CometChat . RECEIVER_TYPE . USER
);
textMessage . setParentMessageId ( parentMessageId );
CometChat . sendMessage ( textMessage ). then (
( message ) => console . log ( "Thread reply sent:" , message ),
( error ) => console . log ( "Failed to send:" , error )
);
const receiverID = "GUID" ;
const parentMessageId = 100 ;
const mediaMessage = new CometChat . MediaMessage (
receiverID ,
file ,
CometChat . MESSAGE_TYPE . IMAGE ,
CometChat . RECEIVER_TYPE . GROUP
);
mediaMessage . setParentMessageId ( parentMessageId );
CometChat . sendMediaMessage ( mediaMessage ). then (
( message ) => console . log ( "Media sent in thread:" , message ),
( error ) => console . log ( "Failed to send:" , error )
);
const receiverID : string = "UID" ;
const parentMessageId : number = 100 ;
const textMessage : CometChat . TextMessage = new CometChat . TextMessage (
receiverID ,
"This is a reply in the thread" ,
CometChat . RECEIVER_TYPE . USER
);
textMessage . setParentMessageId ( parentMessageId );
CometChat . sendMessage ( textMessage ). then (
( message : CometChat . TextMessage ) => console . log ( "Thread reply sent:" , message ),
( error : CometChat . CometChatException ) => console . log ( "Failed to send:" , error )
);
const sendThreadReply = async () => {
try {
const receiverID = "UID" ;
const parentMessageId = 100 ;
const textMessage = new CometChat . TextMessage (
receiverID ,
"This is a reply in the thread" ,
CometChat . RECEIVER_TYPE . USER
);
textMessage . setParentMessageId ( parentMessageId );
const message = await CometChat . sendMessage ( textMessage );
console . log ( "Thread reply sent:" , message );
} catch ( error ) {
console . log ( "Failed to send:" , error );
}
};
Fetch Thread Messages
Retrieve all messages in a specific thread:
JavaScript
TypeScript
Async/Await
const parentMessageId = 100 ;
const limit = 30 ;
const messagesRequest = new CometChat . MessagesRequestBuilder ()
. setParentMessageId ( parentMessageId )
. setLimit ( limit )
. build ();
messagesRequest . fetchPrevious (). then (
( messages ) => console . log ( "Thread messages:" , messages ),
( error ) => console . log ( "Failed to fetch:" , error )
);
const parentMessageId : number = 100 ;
const limit : number = 30 ;
const messagesRequest : CometChat . MessagesRequest = new CometChat . MessagesRequestBuilder ()
. setParentMessageId ( parentMessageId )
. setLimit ( limit )
. build ();
messagesRequest . fetchPrevious (). then (
( messages : CometChat . BaseMessage []) => console . log ( "Thread messages:" , messages ),
( error : CometChat . CometChatException ) => console . log ( "Failed to fetch:" , error )
);
const fetchThreadMessages = async () => {
try {
const parentMessageId = 100 ;
const limit = 30 ;
const messagesRequest = new CometChat . MessagesRequestBuilder ()
. setParentMessageId ( parentMessageId )
. setLimit ( limit )
. build ();
const messages = await messagesRequest . fetchPrevious ();
console . log ( "Thread messages:" , messages );
} catch ( error ) {
console . log ( "Failed to fetch:" , error );
}
};
Use fetchPrevious() to load older messages and fetchNext() to load newer ones. Maximum 100 messages per request.
Real-Time Thread Messages
Listen for new messages in a thread:
const listenerID = "THREAD_LISTENER" ;
const activeThreadId = 100 ;
CometChat . addMessageListener (
listenerID ,
new CometChat . MessageListener ({
onTextMessageReceived : ( message ) => {
if ( message . getParentMessageId () === activeThreadId ) {
console . log ( "New thread message:" , message );
}
},
onMediaMessageReceived : ( message ) => {
if ( message . getParentMessageId () === activeThreadId ) {
console . log ( "New media in thread:" , message );
}
},
onCustomMessageReceived : ( message ) => {
if ( message . getParentMessageId () === activeThreadId ) {
console . log ( "New custom message in thread:" , message );
}
}
})
);
// Remove listener when done
CometChat . removeMessageListener ( listenerID );
Hide Thread Replies in Main Chat
By default, thread replies appear in the main message list. To show only parent messages:
JavaScript
TypeScript
Async/Await
const GUID = "GUID" ;
const limit = 30 ;
const messagesRequest = new CometChat . MessagesRequestBuilder ()
. setGUID ( GUID )
. setLimit ( limit )
. hideReplies ( true ) // Exclude thread replies
. build ();
messagesRequest . fetchPrevious (). then (
( messages ) => console . log ( "Messages (without thread replies):" , messages ),
( error ) => console . log ( "Failed to fetch:" , error )
);
const GUID : string = "GUID" ;
const limit : number = 30 ;
const messagesRequest : CometChat . MessagesRequest = new CometChat . MessagesRequestBuilder ()
. setGUID ( GUID )
. setLimit ( limit )
. hideReplies ( true )
. build ();
messagesRequest . fetchPrevious (). then (
( messages : CometChat . BaseMessage []) => console . log ( "Messages:" , messages ),
( error : CometChat . CometChatException ) => console . log ( "Failed to fetch:" , error )
);
const fetchMessagesWithoutReplies = async () => {
try {
const GUID = "GUID" ;
const limit = 30 ;
const messagesRequest = new CometChat . MessagesRequestBuilder ()
. setGUID ( GUID )
. setLimit ( limit )
. hideReplies ( true ) // Exclude thread replies
. build ();
const messages = await messagesRequest . fetchPrevious ();
console . log ( "Messages (without thread replies):" , messages );
} catch ( error ) {
console . log ( "Failed to fetch:" , error );
}
};
Get Thread Reply Count
Check how many replies a message has:
const replyCount = message . getReplyCount ();
console . log ( `This message has ${ replyCount } replies` );
Complete Implementation
class ThreadManager {
constructor () {
this . activeThreadId = null ;
this . threadMessages = [];
this . listenerID = "thread-manager" ;
}
async openThread ( parentMessageId ) {
this . activeThreadId = parentMessageId ;
this . threadMessages = [];
this . setupListener ();
await this . fetchThreadMessages ();
}
setupListener () {
CometChat . addMessageListener (
this . listenerID ,
new CometChat . MessageListener ({
onTextMessageReceived : ( msg ) => this . handleNewMessage ( msg ),
onMediaMessageReceived : ( msg ) => this . handleNewMessage ( msg ),
onCustomMessageReceived : ( msg ) => this . handleNewMessage ( msg )
})
);
}
handleNewMessage ( message ) {
if ( message . getParentMessageId () === this . activeThreadId ) {
this . threadMessages . push ( message );
this . renderThread ();
}
}
async fetchThreadMessages () {
const request = new CometChat . MessagesRequestBuilder ()
. setParentMessageId ( this . activeThreadId )
. setLimit ( 50 )
. build ();
try {
this . threadMessages = await request . fetchPrevious ();
this . renderThread ();
} catch ( error ) {
console . log ( "Failed to fetch thread:" , error );
}
}
async sendReply ( text , receiverID , receiverType ) {
const message = new CometChat . TextMessage ( receiverID , text , receiverType );
message . setParentMessageId ( this . activeThreadId );
try {
const sent = await CometChat . sendMessage ( message );
console . log ( "Reply sent:" , sent );
} catch ( error ) {
console . log ( "Failed to send reply:" , error );
}
}
renderThread () {
console . log ( `Thread has ${ this . threadMessages . length } messages` );
// Update your UI here
}
closeThread () {
CometChat . removeMessageListener ( this . listenerID );
this . activeThreadId = null ;
this . threadMessages = [];
}
}
// Usage
const threadManager = new ThreadManager ();
await threadManager . openThread ( 100 );
await threadManager . sendReply ( "Great idea!" , "group-123" , CometChat . RECEIVER_TYPE . GROUP );
threadManager . closeThread ();
Best Practices
Show reply count on parent messages to indicate threads exist
Use a slide-out panel or modal for thread views
Keep the parent message visible at the top of the thread
Show “View in thread” link when displaying thread replies in main chat
Update reply count on parent message when new replies arrive
Show typing indicators within thread context
Handle message edits and deletes in threads
Next Steps