# Thread messages (/en/realtime-media/im/build/build-groups-rooms-and-threads/threading/thread-messages/react-native)

> For AI agents: see the complete documentation index at [llms.txt](/llms.txt).

Threads enable users to create a separate conversation from a specific message within a chat group to keep the main chat uncluttered.

    This page shows how to use the Chat SDK to send, receive, recall, and retrieve thread messages in your app.

    ## Understand the tech [#understand-the-tech-4]

    The Chat SDK provides the `ChatManager`, `ChatMessage`, and `ChatMessageThread` classes for thread messages, which allows you to implement the following features:

    ## Prerequisites [#prerequisites-4]

    Before proceeding, ensure that you meet the following requirements:

    * You have initialized the Chat SDK. For details, see [SDK quickstart](../../../get-started-sdk).
    * You understand the call frequency limit of the Chat APIs supported by different pricing plans as described in [Limitations](../../limitations).

    <CalloutContainer type="info">
      <CalloutDescription>
        The thread feature is supported by all types of [Pricing Plans](../../../reference/pricing-plan-details) and is enabled by default once you have enabled Chat in [Agora Console](https://console.agora.io/v2).
      </CalloutDescription>
    </CalloutContainer>

    ## Implementation [#implementation-4]

    This section describes how to call the APIs provided by the Chat SDK to implement thread features.

    ### Send a thread message [#send-a-thread-message-4]

    Sending a thread message is similar to sending a message in a chat group. The difference lies in the `isChatThread` field, as shown in the following code sample:

    ```typescript
    // Sets `chatThreadId` to the thread ID.
    // Sets `content` to the message content.
    // Sets `chatType` to `GroupChat` as a thread belongs to a chat group.
    // Sets `isChatThread` to `true` to mark this message as a thread message.
    const message = ChatMessage.createTextMessage(chatThreadId, content, chatType, {
      isChatThread: true,
    });
    // Implements `ChatMessageCallback` to listen for the message sending event.
    const callback = new ChatMessageCallback();
    // Sends the message.
    ChatClient.getInstance()
      .chatManager.sendMessage(message, callback)
      .then(() => {
        // Prints the log here if the method call succeeds.
        console.log("send message operation success.");
      })
      .catch((reason) => {
        // Prints the log here if the method call fails.
        console.log("send message operation fail.", reason);
      });
    ```

    For more information about sending a message, see [Send Messages](../../build-core-messaging/messages/send-receive-messages#send-a-text-message).

    ### Receive a thread message [#receive-a-thread-message-4]

    Once a thread has a new message, all chat group members receive the `ChatMessageEventListener#onChatMessageThreadUpdated` callback. Thread members can also listen for the `ChatMessageEventListener#onMessagesReceived` callback to receive thread messages, as shown in the following code sample:

    ```typescript
    // Inherits and implements `ChatMessageEventListener`.
    class ChatMessageEvent implements ChatMessageEventListener {
      // Occurs when a message is received.
      onMessagesReceived(messages: ChatMessage[]): void {
        console.log(`onMessagesReceived: `, messages);
      }
      // Occurs when the thread has a new message.
      onChatMessageThreadUpdated(msgThread: ChatMessageThreadEvent): void {
        console.log(`onChatMessageThreadUpdated: `, msgThread);
      }
    }
    // Adds the message listener.
    const listener = new ChatMessageEvent();
    ChatClient.getInstance().chatManager.addMessageListener(listener);
    // Removes the message listener.
    ChatClient.getInstance().chatManager.removeMessageListener(listener);
    // Removes all the message listeners.
    ChatClient.getInstance().chatManager.removeAllMessageListener();
    ```

    For more information about receiving a message, see [Receive Messages](../../build-core-messaging/messages/send-receive-messages#receive-a-message).

    ### Recall a thread message [#recall-a-thread-message-4]

    For details about how to recall a message, refer to [Recall Messages](../../build-core-messaging/messages/send-receive-messages#recall-a-message).

    Once a message is recalled in a thread, all chat group members receive the `ChatMessageEventListener#onChatMessageThreadUpdated` callback. Thread members can also listen for the `ChatMessageEventListener#onMessagesRecalled` callback, as shown in the following code sample:

    ```typescript
    // Inherits and implements `ChatMessageEventListener`.
    class ChatMessageEvent implements ChatMessageEventListener {
      // Occurs when a message is recalled.
      onMessagesRecalled(messages: ChatMessage[]): void {
        console.log(`onMessagesRecalled: `, messages);
      }
      // Occurs when a thread message is recalled.
      onChatMessageThreadUpdated(msgThread: ChatMessageThreadEvent): void {
        console.log(`onChatMessageThreadUpdated: `, msgThread);
      }
    }
    ```

    ### Retrieve thread messages [#retrieve-thread-messages-3]

    You can retrieve thread messages locally or from the server, depending on your production environment.

    You can check `ChatConversation#isChatThread()` to determine whether the current conversation is a thread conversation.

    #### Retrieve messages of a thread from the server [#retrieve-messages-of-a-thread-from-the-server-4]

    You can call `asyncFetchHistoryMessage` to retrieve messages of a thread from the server. The only difference between retrieving messages of a thread from the server and retrieving group messages is that a thread ID needs to be passed in for the former and a group ID is required for the latter.

    ```typescript
    // chatThreadID: The thread ID.
    const chatThreadID = "chatThreadID";
    // The chat type is set to ChatConversationType.GroupChat as a thread belongs to a group.
    const convType = ChatConversationType.GroupChat;
    // The number of thread messages that you expect to get on each page.
    const pageSize = 10;
    // The starting message ID for retrieving.
    const startMsgId = "";
    // The message search direction.
    const direction = ChatSearchDirection.UP;
    ChatClient.getInstance()
      .chatManager.fetchHistoryMessages(chatThreadID, chatType, {
        pageSize,
        startMsgId,
        direction,
      })
      .then((messages) => {
        console.log("get message success: ", messages);
      })
      .catch((reason) => {
        console.log("load conversions fail.", reason);
      });
    ```

    #### Retrieve messages of a thread locally [#retrieve-messages-of-a-thread-locally-3]

    By calling [`getAllConversations`](../../build-core-messaging/messages/manage-messages#retrieve-conversations), you can only retrieve local one-to-one chat conversations and group conversations. To retrieve messages of a thread locally, refer to the following code sample:

    ```typescript
    // Gets a thread conversation.
    ChatClient.getInstance()
      .chatManager.getThreadConversation(chatThreadID, createIfNeed)
      .then((conv) => {
        // Gets messages of the thread from the local database. The SDK automatically loads and stores the retrieved messages to the memory.
        conv
          .getMessages(
            chatThreadID,
            ChatConversationType.GroupChat,
            startMsgId,
            direction,
            loadCount
          )
          .then((messages) => {
            console.log("success.", messages);
          })
          .catch((reason) => {
            console.log("fail.", reason);
          });
      })
      .catch((reason) => {
        console.log("fail.", reason);
      });
    ```

    
  
      
  
      
  
