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

# Typing Indicators

> Learn how to send and receive real-time typing indicators in one-on-one and group conversations using the CometChat React Native SDK.

<Info>
  **Quick Reference** — Send and listen for typing indicators:

  ```javascript theme={null}
  // Start typing
  let typing = new CometChat.TypingIndicator("RECEIVER_ID", CometChat.RECEIVER_TYPE.USER);
  CometChat.startTyping(typing);

  // Stop typing
  CometChat.endTyping(typing);

  // Listen for typing events
  CometChat.addMessageListener("listenerId", new CometChat.MessageListener({
    onTypingStarted: (indicator) => { /* sender is typing */ },
    onTypingEnded: (indicator) => { /* sender stopped typing */ },
  }));
  ```
</Info>

<Note>
  **Available via:** [SDK](/sdk/react-native/typing-indicators)  | [UI Kits](/ui-kit/react-native/core-features#typing-indicator)
</Note>

## Send a Typing Indicator

*In other words, as a sender, how do I let the recipient(s) know that I'm typing?*

### Start Typing

You can use the `startTyping()` method to inform the receiver that the logged-in user has started typing. The receiver will receive this information in the `onTypingStarted()` method of the `MessageListener` class. To send the typing indicator, you need to use the `TypingIndicator` class.

<Tabs>
  <Tab title="To User">
    ```javascript theme={null}
    let receiverId = "UID";
    let receiverType = CometChat.RECEIVER_TYPE.USER;

    let typingNotification = new CometChat.TypingIndicator(receiverId, receiverType);
    CometChat.startTyping(typingNotification);
    ```
  </Tab>

  <Tab title="To Group">
    ```javascript theme={null}
    let receiverId = "GUID";
    let receiverType = CometChat.RECEIVER_TYPE.GROUP;

    let typingNotification = new CometChat.TypingIndicator(receiverId,receiverType);
    CometChat.startTyping(typingNotification);
    ```
  </Tab>

  <Tab title="TypeScript (User)">
    ```typescript theme={null}
    let receiverId: string = "UID";
    let receiverType: string = CometChat.RECEIVER_TYPE.USER;

    let typingNotification: CometChat.TypingIndicator = new CometChat.TypingIndicator(receiverId, receiverType);
    CometChat.startTyping(typingNotification);
    ```
  </Tab>

  <Tab title="TypeScript (Group)">
    ```typescript theme={null}
    let receiverId: string = "GUID";
    let receiverType: string = CometChat.RECEIVER_TYPE.GROUP;

    let typingNotification: CometChat.TypingIndicator = new CometChat.TypingIndicator(receiverId, receiverType);
    CometChat.startTyping(typingNotification);
    ```
  </Tab>
</Tabs>

<Accordion title="Response">
  **startTyping called** — the typing indicator object sent to the receiver:

  | Parameter      | Type   | Description                  | Sample Value        |
  | -------------- | ------ | ---------------------------- | ------------------- |
  | `receiverId`   | string | Receiver's unique identifier | `"cometchat-uid-6"` |
  | `receiverType` | string | Type of receiver             | `"user"`            |
</Accordion>

### Stop Typing

You can use the `endTyping()` method to inform the receiver that the logged-in user has stopped typing. The receiver will receive this information in the `onTypingEnded()` method of the `MessageListener` class. To send the typing indicator, you need to use the `TypingIndicator` class.

<Tabs>
  <Tab title="To User">
    ```javascript theme={null}
    let receiverId = "UID";
    let receiverType = CometChat.RECEIVER_TYPE.USER;

    let typingNotification = new CometChat.TypingIndicator(receiverId, receiverType);
    CometChat.endTyping(typingNotification);
    ```
  </Tab>

  <Tab title="To Group">
    ```javascript theme={null}
    let receiverId = "GUID";
    let receiverType = CometChat.RECEIVER_TYPE.GROUP;

    let typingNotification = new CometChat.TypingIndicator(receiverId, receiverType);
    CometChat.endTyping(typingNotification);
    ```
  </Tab>

  <Tab title="TypeScript (User)">
    ```typescript theme={null}
    let receiverId: string = "UID";
    let receiverType: string = CometChat.RECEIVER_TYPE.USER;

    let typingNotification: CometChat.TypingIndicator = new CometChat.TypingIndicator(receiverId, receiverType);
    CometChat.endTyping(typingNotification);
    ```
  </Tab>

  <Tab title="TypeScript (Group)">
    ```typescript theme={null}
    let receiverId: string = "GUID";
    let receiverType: string = CometChat.RECEIVER_TYPE.GROUP;

    let typingNotification: CometChat.TypingIndicator = new CometChat.TypingIndicator(receiverId, receiverType);
    CometChat.endTyping(typingNotification);
    ```
  </Tab>
</Tabs>

<Accordion title="Response">
  **endTyping called** — the typing indicator object sent to the receiver:

  | Parameter      | Type   | Description                  | Sample Value        |
  | -------------- | ------ | ---------------------------- | ------------------- |
  | `receiverId`   | string | Receiver's unique identifier | `"cometchat-uid-6"` |
  | `receiverType` | string | Type of receiver             | `"user"`            |
</Accordion>

<Note>
  Custom Data

  You can use the `metadata` field of the `TypingIndicator` class to pass additional data along with the typing indicators. The metadata field is a JSONObject and can be set using the `setMetadata()` method of the `TypingIndicator` class. This data will be received at the receiver end and can be obtained using the `getMetadata()` method.
</Note>

## Real-time Typing Indicators

*In other words, as a recipient, how do I know when someone is typing?*

You will receive the typing indicators in the `onTypingStarted()` and the `onTypingEnded()` method of the registered `MessageListener` class.

<Tabs>
  <Tab title="JavaScript">
    ```javascript theme={null}
    let listenerId = "UNIQUE_LITENER_ID";

    CometChat.addMessageListener(
    listenerId,
    new CometChat.MessageListener({
      onTypingStarted: typingIndicator => {
        console.log("Typing started :", typingIndicator);
      },
      onTypingEnded: typingIndicator => {
        console.log("Typing ended :", typingIndicator);
      }
    })
    );
    ```
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={null}
    let listenerId: string = "UNIQUE_LITENER_ID";

    CometChat.addMessageListener(
      listenerId,
      new CometChat.MessageListener({
          onTypingStarted: (typingIndicator: CometChat.TypingIndicator) => {
              console.log("Typing started :", typingIndicator);
          },
          onTypingEnded: (typingIndicator: CometChat.TypingIndicator) => {
              console.log("Typing ended :", typingIndicator);
          }
      })
    );
    ```
  </Tab>
</Tabs>

<Accordion title="Response">
  **onTypingStarted** — received when a user starts typing:

  <span id="typing-started-object" style={{scrollMarginTop: '100px'}} />

  **TypingIndicator Object:**

  | Parameter      | Type   | Description                  | Sample Value                                 |
  | -------------- | ------ | ---------------------------- | -------------------------------------------- |
  | `receiverId`   | string | Receiver's unique identifier | `"cometchat-uid-7"`                          |
  | `receiverType` | string | Type of receiver             | `"user"`                                     |
  | `sender`       | object | User who is typing           | [See below ↓](#typing-started-sender-object) |

  ***

  <span id="typing-started-sender-object" style={{scrollMarginTop: '100px'}} />

  **`sender` Object:**

  | Parameter       | Type    | Description                            | Sample Value                                                            |
  | --------------- | ------- | -------------------------------------- | ----------------------------------------------------------------------- |
  | `uid`           | string  | User's unique identifier               | `"cometchat-uid-6"`                                                     |
  | `name`          | string  | User's display name                    | `"Ronald Jerry"`                                                        |
  | `avatar`        | string  | URL to user's avatar                   | `"https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-6.webp"` |
  | `status`        | string  | User's online status                   | `"online"`                                                              |
  | `role`          | string  | User's role                            | `"default"`                                                             |
  | `hasBlockedMe`  | boolean | Whether user has blocked current user  | `false`                                                                 |
  | `blockedByMe`   | boolean | Whether current user blocked this user | `false`                                                                 |
  | `deactivatedAt` | number  | Deactivation timestamp (0 if active)   | `0`                                                                     |
  | `tags`          | array   | User tags                              | `[]`                                                                    |

  ***

  **onTypingEnded** — received when a user stops typing:

  <span id="typing-ended-object" style={{scrollMarginTop: '100px'}} />

  **TypingIndicator Object:**

  | Parameter      | Type   | Description                  | Sample Value                               |
  | -------------- | ------ | ---------------------------- | ------------------------------------------ |
  | `receiverId`   | string | Receiver's unique identifier | `"cometchat-uid-7"`                        |
  | `receiverType` | string | Type of receiver             | `"user"`                                   |
  | `sender`       | object | User who stopped typing      | [See below ↓](#typing-ended-sender-object) |

  ***

  <span id="typing-ended-sender-object" style={{scrollMarginTop: '100px'}} />

  **`sender` Object:**

  | Parameter       | Type    | Description                            | Sample Value                                                            |
  | --------------- | ------- | -------------------------------------- | ----------------------------------------------------------------------- |
  | `uid`           | string  | User's unique identifier               | `"cometchat-uid-6"`                                                     |
  | `name`          | string  | User's display name                    | `"Ronald Jerry"`                                                        |
  | `avatar`        | string  | URL to user's avatar                   | `"https://assets.cometchat.io/sampleapp/v2/users/cometchat-uid-6.webp"` |
  | `status`        | string  | User's online status                   | `"online"`                                                              |
  | `role`          | string  | User's role                            | `"default"`                                                             |
  | `hasBlockedMe`  | boolean | Whether user has blocked current user  | `false`                                                                 |
  | `blockedByMe`   | boolean | Whether current user blocked this user | `false`                                                                 |
  | `deactivatedAt` | number  | Deactivation timestamp (0 if active)   | `0`                                                                     |
  | `tags`          | array   | User tags                              | `[]`                                                                    |
</Accordion>

<Warning>
  **Listener Cleanup** — Always remove your message listeners when the component unmounts to prevent memory leaks and unexpected behavior. Use `CometChat.removeMessageListener("UNIQUE_LITENER_ID")` in your cleanup logic (e.g., inside a `useEffect` return function or `componentWillUnmount`).
</Warning>

The `TypingIndicator` class consists of the below parameters:

| Parameter        | Information                                                                                                                                                                        |
| ---------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **sender**       | An object of the `User` class holding all the information related to the sender of the typing indicator.                                                                           |
| **receiverId**   | Unique Id of the receiver. This can be the Id of the group or the user the typing indicator is sent to.                                                                            |
| **receiverType** | This parameter indicates if the typing indicator is to be sent to a user or a group. The possible values are: 1. `CometChat.RECEIVER_TYPE.USER` 2. `CometChat.RECEIVER_TYPE.GROUP` |
| **metadata**     | A JSONObject to provide additional data.                                                                                                                                           |

<AccordionGroup>
  <Accordion title="Best Practices">
    * **Debounce start typing calls** — Avoid calling `startTyping()` on every keystroke. Instead, debounce the call so it fires once when the user begins typing and doesn't repeat until after a short pause.
    * **Call endTyping() explicitly** — Always call `endTyping()` when the user clears the input field, sends a message, or navigates away from the chat screen.
    * **Use unique listener IDs** — Each screen or component that registers a `MessageListener` should use a distinct `listenerId` to avoid conflicts.
    * **Handle metadata sparingly** — Only attach `metadata` to typing indicators when you have a concrete use case (e.g., indicating which thread the user is typing in).
  </Accordion>

  <Accordion title="Troubleshooting">
    * **Typing indicator not appearing for the recipient** — Verify that the recipient has registered a `MessageListener` with `onTypingStarted` and `onTypingEnded` callbacks before the sender starts typing.
    * **Typing indicator stuck in "typing" state** — Ensure `endTyping()` is called when the user stops typing or sends a message. CometChat automatically times out typing indicators after a short period, but explicitly ending them provides a better user experience.
    * **Listener not firing** — Confirm that the `listenerId` used in `addMessageListener` is unique and that the listener has not been removed prematurely.
    * **Indicators not working in groups** — Make sure you are using `CometChat.RECEIVER_TYPE.GROUP` with the correct group ID (`GUID`), not a user ID.
  </Accordion>
</AccordionGroup>

## Next Steps

<CardGroup cols={2}>
  <Card title="Delivery & Read Receipts" icon="check-double" href="/sdk/react-native/delivery-read-receipts">
    Confirm when messages are delivered and read by recipients.
  </Card>

  <Card title="Send a Message" icon="paper-plane" href="/sdk/react-native/send-message">
    Learn how to send text, media, and custom messages.
  </Card>

  <Card title="Receive Messages" icon="inbox" href="/sdk/react-native/receive-messages">
    Set up real-time and fetch-based message receiving.
  </Card>

  <Card title="Messaging Overview" icon="comments" href="/sdk/react-native/messaging-overview">
    Explore the full messaging feature set available in the SDK.
  </Card>
</CardGroup>
