> ## Documentation Index
> Fetch the complete documentation index at: https://cometchat-22654f5b-docs-js-sdk-llms-index.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Threaded Messages

> Send, receive, and fetch threaded messages with the CometChat JavaScript SDK.

<Accordion title="AI Integration Quick Reference">
  | Field                | Value                                                                                                                                                                                                                                                                                                                                                                    |
  | -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
  | Package              | `@cometchat/chat-sdk-javascript`                                                                                                                                                                                                                                                                                                                                         |
  | Import               | `import { CometChat } from "@cometchat/chat-sdk-javascript";`                                                                                                                                                                                                                                                                                                            |
  | Key methods          | `textMessage.setParentMessageId(messageId)` · `CometChat.sendMessage(textMessage)` · `CometChat.addMessageListener(listenerID, new CometChat.MessageListener({...}))` · `message.getParentMessageId()` · `new CometChat.MessagesRequestBuilder().setParentMessageId(parentMessageId).setLimit(limit).build()` · `messagesRequest.fetchPrevious()` · `.hideReplies(true)` |
  | Key classes          | `CometChat.MessageListener` · `CometChat.MessagesRequestBuilder` · `CometChat.MessagesRequest` · `CometChat.TextMessage` · `CometChat.MediaMessage` · `CometChat.CustomMessage` · `CometChat.BaseMessage`                                                                                                                                                                |
  | Primary output       | `sendMessage()` resolves to the sent message (e.g. `TextMessage`); `fetchPrevious()` resolves to `Promise<CometChat.BaseMessage[]>` (thread replies, or top-level messages when `hideReplies(true)` is set); real-time thread messages arrive on the `MessageListener`; all reject with `CometChat.CometChatException`                                                   |
  | Listeners registered | `MessageListener` via `CometChat.addMessageListener(listenerID, ...)` / `CometChat.removeMessageListener(listenerID)` — callbacks: `onTextMessageReceived`, `onMediaMessageReceived`, `onCustomMessageReceived`; filter to the active thread with `getParentMessageId()`                                                                                                 |
  | Prerequisites        | SDK initialized via [`CometChat.init()`](/sdk/javascript/setup-sdk) and a logged-in user via [`CometChat.login()`](/sdk/javascript/authentication-overview); a parent message ID to thread under                                                                                                                                                                         |
  | Constraints          | `fetchPrevious()` returns at most 100 messages per request. Use `hideReplies(true)` on the builder to exclude thread replies and return only top-level messages. Always remove listeners on unmount to avoid memory leaks and duplicate handling                                                                                                                         |
  | Related              | [Send a Message](/sdk/javascript/send-message) · [Receive a Message](/sdk/javascript/receive-message) · [Message Filtering](/sdk/javascript/message-filtering) · [Reactions](/sdk/javascript/reactions)                                                                                                                                                                  |
  | Full reference       | [`BaseMessage`](/sdk/reference/messages#basemessage) · [`TextMessage`](/sdk/reference/messages#textmessage) · [`MediaMessage`](/sdk/reference/messages#mediamessage) · [`CustomMessage`](/sdk/reference/messages#custommessage)                                                                                                                                          |
</Accordion>

Messages that are started from a particular message are called Threaded messages or simply threads. Each Thread is attached to a message which is the Parent message for that thread.

## Send Message in a Thread

Any message type (Text, Media, or Custom) can be sent in a thread. Set the `parentMessageId` using `setParentMessageId()` to indicate which thread the message belongs to.

<Tabs>
  <Tab title="TypeScript">
    ```typescript theme={null}
    let receiverId = "UID",
      receiverType: string = CometChat.RECEIVER_TYPE.USER,
      textMessage: CometChat.TextMessage = new CometChat.TextMessage(receiverId, "Hello", receiverType),
      messageId: number = 100;

    textMessage.setParentMessageId(messageId);

    CometChat.sendMessage(textMessage).then(
    (message: CometChat.TextMessage) => {
    console.log('Message sent successfully', message);
    }, (error: CometChat.CometChatException) => {
    console.log('Message sending failed', error);
    }
    );

    ```
  </Tab>

  <Tab title="JavaScript">
    ```javascript theme={null}
    let UID = "UID";
    let textMessage = new CometChat.TextMessage(UID, "Hello", CometChat.RECEIVER_TYPE.USER);
    textMessage.setParentMessageId(100);

    CometChat.sendMessage(textMessage).then(
      message => {
          console.log('Message sent successfully', message);
      }, err => {
          console.log('err', err);
      }
    )
    ```
  </Tab>
</Tabs>

The above snippet sends "Hello" in the thread with `parentMessageId` 100. Media and Custom messages can also be sent in threads using `setParentMessageId()`.

### Receiving Real-Time Messages

Use `MessageListener` to receive real-time thread messages. Check if the received message belongs to the active thread using `getParentMessageId()`.

<Tabs>
  <Tab title="TypeScript">
    ```typescript theme={null}
    const listenerID: string = "UNIQUE_LISTENER_ID";
    const activeThreadId: number = 100;

    CometChat.addMessageListener(
    listenerID,
    new CometChat.MessageListener({
    onTextMessageReceived: (textMessage: CometChat.TextMessage) => {
    if (textMessage.getParentMessageId() == activeThreadId) {
    console.log("Text message received for active thread.", textMessage);
    }
    },
    onMediaMessageReceived: (mediaMessage: CometChat.MediaMessage) => {
    if (mediaMessage.getParentMessageId() == activeThreadId) {
    console.log("Media message received for active thread.", mediaMessage);
    }
    },
    onCustomMessageReceived: (customMessage: CometChat.CustomMessage) => {
    if (customMessage.getParentMessageId() == activeThreadId) {
    console.log("Custom message received for active thread.", customMessage);
    }
    }
    })
    );

    ```
  </Tab>

  <Tab title="JavaScript">
    ```javascript theme={null}
    const listenerID = "UNIQUE_LISTENER_ID";
    const activeThreadId = 100;

    CometChat.addMessageListener(
    listenerID,
    new CometChat.MessageListener({
      onTextMessageReceived: textMessage => {
          if(textMessage.getParentMessageId() == activeThreadId) {
              console.log("Text message received for active thread.", textMessage);
          }
      },
      onMediaMessageReceived: mediaMessage => {
          if(mediaMessage.getParentMessageId() == activeThreadId) {
              console.log("Media message received for active thread.", mediaMessage);
          }
      },
      onCustomMessageReceived: customMessage => {
          if(customMessage.getParentMessageId() == activeThreadId) {
              console.log("Custom message received for active thread.", customMessage);
          }
      }
    })
    );
    ```
  </Tab>
</Tabs>

### Fetch all the messages for any particular thread.

Use `MessagesRequestBuilder` with `setParentMessageId()` to fetch messages belonging to a specific thread. Call `fetchPrevious()` to get messages (max 100 per request).

<Tabs>
  <Tab title="TypeScript">
    ```typescript theme={null}
    let limit: number = 30,
      parentMessageId: number = 1,
      messagesRequest: CometChat.MessagesRequest = new CometChat.MessagesRequestBuilder()
          .setLimit(limit)
          .setParentMessageId(parentMessageId)
          .build();

    messagesRequest.fetchPrevious().then(
    (messages: CometChat.BaseMessage[]) => {
    console.log("Messages for thread fetched successfully", messages);
    }, (error: CometChat.CometChatException) => {
    console.log("Message fetching failed with error:", error);
    }
    );

    ```
  </Tab>

  <Tab title="JavaScript">
    ```javascript theme={null}
    let limit = 30;
    let parentMessageId = 1;
    let messagesRequest = new CometChat.MessagesRequestBuilder()
                          .setLimit(limit)
                          .setParentMessageId(parentMessageId)
                          .build();

    messagesRequest.fetchPrevious().then(
      messages => {
          console.log("Messages for thread fetched successfully", messages);
      }, error => {
          console.log("Message fetching failed with error:", error);
      }
    );
    ```
  </Tab>
</Tabs>

The `fetchPrevious()` method returns an array of [`BaseMessage`](/sdk/reference/messages#basemessage) objects representing thread replies.

## Avoid Threaded Messages in User/Group Conversations

Use `hideReplies(true)` to exclude threaded messages when fetching messages for a conversation.

<Tabs>
  <Tab title="TypeScript (User)">
    ```typescript theme={null}
    let UID: string = "UID",
      limit: number = 30,
      messagesRequest: CometChat.MessagesRequest = new CometChat.MessagesRequestBuilder()
          .setUID(UID)
          .setLimit(limit)
          .hideReplies(true)
          .build();

    messagesRequest.fetchPrevious().then(
    (messages: CometChat.BaseMessage[]) => {
    console.log("Messages fetched successfully", messages);
    }, (error: CometChat.CometChatException) => {
    console.log("Message fetching failed with error:", error);
    }
    );

    ```
  </Tab>

  <Tab title="JavaScript (User)">
    ```javascript theme={null}
    let UID = "UID";
    let limit = 30;
    let messagesRequest = new CometChat.MessagesRequestBuilder()
                          .setUID(UID)
                          .setLimit(limit)
                          .hideReplies(true)
                          .build();

    messagesRequest.fetchPrevious().then(
      messages => {
          console.log("Messages fetched successfully", messages);
      }, error => {
          console.log("Message fetching failed with error:", error);
      }
    );
    ```
  </Tab>

  <Tab title="TypeScript (Group)">
    ```typescript theme={null}
    let GUID: string = "GUID",
      limit: number = 30,
      messagesRequest: CometChat.MessagesRequest = new CometChat.MessagesRequestBuilder()
          .setGUID(GUID)
          .setLimit(limit)
          .hideReplies(true)
          .build();

    messagesRequest.fetchPrevious().then(
    (messages: CometChat.BaseMessage[]) => {
    console.log("Messages fetched successfully", messages);
    }, (error: CometChat.CometChatException) => {
    console.log("Message fetching failed with error:", error);
    }
    );

    ```
  </Tab>

  <Tab title="JavaScript (Group)">
    ```javascript theme={null}
    let GUID = "GUID";
    let limit = 30;
    let messagesRequest = new CometChat.MessagesRequestBuilder()
                          .setGUID(GUID)
                          .setLimit(limit)
                          .hideReplies(true)
                          .build();

    messagesRequest.fetchPrevious().then(
      messages => {
          console.log("Messages fetched successfully", messages);
      }, error => {
          console.log("Message fetching failed with error:", error);
      }
    );
    ```
  </Tab>
</Tabs>

The response is an array of [`BaseMessage`](/sdk/reference/messages#basemessage) objects, excluding any messages that are replies within a thread. Only top-level messages in the conversation are returned.

<Warning>
  Always remove message listeners when they're no longer needed (e.g., on component unmount or page navigation). Failing to remove listeners can cause memory leaks and duplicate event handling.

  ```javascript theme={null}
  CometChat.removeMessageListener("UNIQUE_LISTENER_ID");
  ```
</Warning>

***

## Next Steps

<CardGroup cols={2}>
  <Card title="Send Messages" icon="paper-plane" href="/sdk/javascript/send-message">
    Send text, media, and custom messages to users and groups
  </Card>

  <Card title="Receive Messages" icon="inbox" href="/sdk/javascript/receive-message">
    Listen for incoming messages in real-time and fetch missed messages
  </Card>

  <Card title="Reactions" icon="face-smile" href="/sdk/javascript/reactions">
    Add emoji reactions to messages
  </Card>

  <Card title="Message Filtering" icon="filter" href="/sdk/javascript/message-filtering">
    Advanced message filtering with RequestBuilder
  </Card>
</CardGroup>
