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

# Reactions

> Guide to adding, removing, and fetching message reactions using the CometChat iOS SDK with real-time reaction events.

<Info>
  **Quick Reference for AI Agents & Developers**

  * **Add reaction:** `CometChat.addReaction(messageId:reaction:onSuccess:onError:)`
  * **Remove reaction:** `CometChat.removeReaction(messageId:reaction:onSuccess:onError:)`
  * **Fetch reactions:** `ReactionsRequestBuilder().setMessageId(messageId:).build()` → `fetchNext(onSuccess:onError:)`
  * **Listen for reactions:** `onMessageReactionAdded(_:)`, `onMessageReactionRemoved(_:)` in message listener
  * **Related:** [Send Message](/sdk/ios/send-message) · [Messaging Overview](/sdk/ios/messaging-overview)
</Info>

Enhance user engagement in your chat application with message reactions. Users can express their emotions using reactions to messages. This feature allows users to add or remove reactions, and to fetch all reactions on a message.

***

## Add a Reaction

Users can add a reaction to a message by calling `addReaction` with the message ID and the reaction emoji.

<Tabs>
  <Tab title="Swift">
    ```swift theme={null}
    CometChat.addReaction(messageId: 148, reaction: "😴") { message in
        print("Reactions: \(message.getReactions())")
    } onError: { error in
        print("Error: \(error?.errorDescription)")
    }
    ```
  </Tab>
</Tabs>

<Accordion title="Sample Payloads - Add Reaction">
  <Tabs>
    <Tab title="Request">
      **Method:** `CometChat.addReaction(messageId:reaction:)`

      | Parameter | Type     | Value   |
      | --------- | -------- | ------- |
      | messageId | `Int`    | `38230` |
      | reaction  | `String` | `"👍"`  |
    </Tab>

    <Tab title="Success Response">
      **Message Properties:**

      | Parameter     | Type     | Value   |
      | ------------- | -------- | ------- |
      | id            | `Int`    | `38230` |
      | reactionAdded | `String` | `"👍"`  |

      **Reactions List (message.reactions):**

      | Reaction | Count | ReactedByMe |
      | -------- | ----- | ----------- |
      | 👍       | `1`   | `true`      |
    </Tab>

    <Tab title="Error Response">
      **Object Type:** CometChatException

      | Parameter        | Type     | Value                      |
      | ---------------- | -------- | -------------------------- |
      | errorCode        | `String` | `"ERR_MESSAGE_NOT_FOUND"`  |
      | errorDescription | `String` | `"Message does not exist"` |
    </Tab>
  </Tabs>
</Accordion>

<Accordion title="More Sample Payloads - Multiple Reactions">
  <Tabs>
    <Tab title="Add Heart Reaction">
      **Request:**

      | Parameter | Type     | Value   |
      | --------- | -------- | ------- |
      | messageId | `Int`    | `38230` |
      | reaction  | `String` | `"❤️"`  |

      **Updated Reactions List:**

      | Reaction | Count | ReactedByMe |
      | -------- | ----- | ----------- |
      | 👍       | `1`   | `true`      |
      | ❤️       | `1`   | `true`      |
    </Tab>

    <Tab title="Add Laugh Reaction">
      **Request:**

      | Parameter | Type     | Value   |
      | --------- | -------- | ------- |
      | messageId | `Int`    | `38230` |
      | reaction  | `String` | `"😂"`  |

      **Updated Reactions List:**

      | Reaction | Count | ReactedByMe |
      | -------- | ----- | ----------- |
      | 👍       | `1`   | `true`      |
      | ❤️       | `1`   | `true`      |
      | 😂       | `1`   | `true`      |
    </Tab>
  </Tabs>
</Accordion>

<Note>
  You can react on Text, Media and Custom messages.
</Note>

***

## Remove a Reaction

Removing a reaction from a message can be done using the `removeReaction` method.

<Tabs>
  <Tab title="Swift">
    ```swift theme={null}
    CometChat.removeReaction(messageId: 148, reaction: "😴") { message in
        print("Reactions: \(message.getReactions())")
    } onError: { error in
        print("Error: \(error?.errorDescription)")
    }
    ```
  </Tab>
</Tabs>

<Accordion title="Sample Payloads - Remove Reaction">
  <Tabs>
    <Tab title="Request">
      **Method:** `CometChat.removeReaction(messageId:reaction:)`

      | Parameter | Type     | Value   |
      | --------- | -------- | ------- |
      | messageId | `Int`    | `38230` |
      | reaction  | `String` | `"👍"`  |
    </Tab>

    <Tab title="Success Response">
      **Message Properties:**

      | Parameter       | Type     | Value   |
      | --------------- | -------- | ------- |
      | id              | `Int`    | `38230` |
      | reactionRemoved | `String` | `"👍"`  |

      **Updated Reactions List:**

      | Reaction | Count | ReactedByMe |
      | -------- | ----- | ----------- |
      | ❤️       | `1`   | `true`      |
      | 😂       | `1`   | `true`      |
    </Tab>

    <Tab title="Error Response">
      **Object Type:** CometChatException

      | Parameter        | Type     | Value                             |
      | ---------------- | -------- | --------------------------------- |
      | errorCode        | `String` | `"ERR_REACTION_NOT_FOUND"`        |
      | errorDescription | `String` | `"Reaction not found on message"` |
    </Tab>
  </Tabs>
</Accordion>

***

## Fetch Reactions for a Message

To get all reactions for a specific message, create a `ReactionsRequest` using `ReactionsRequestBuilder`.

| Method                          | Description                            |
| ------------------------------- | -------------------------------------- |
| `setMessageId(messageId: Int)`  | Specifies the message ID (required)    |
| `setReaction(reaction: String)` | Filter by specific emoji (optional)    |
| `setLimit(limit: Int)`          | Number of reactions to fetch (max 100) |

### Fetch Next Reactions

<Tabs>
  <Tab title="Swift">
    ```swift theme={null}
    let reactionsRequest = ReactionsRequestBuilder()
        .setLimit(limit: 30)
        .setMessageId(messageId: 148)
        .build()

    reactionsRequest.fetchNext { reactions in
        for reaction in reactions {
            print("Reaction: \(reaction.reaction)")
            print("Reacted by: \(reaction.reactedBy?.name ?? "")")
        }
    } onError: { error in
        print("Error: \(error?.errorDescription)")
    }
    ```
  </Tab>
</Tabs>

<Accordion title="Sample Payloads - Fetch Reactions">
  <Tabs>
    <Tab title="Request">
      **Method:** `ReactionsRequest.fetchNext()`

      | Parameter | Type      | Value                              |
      | --------- | --------- | ---------------------------------- |
      | messageId | `Int`     | `38230`                            |
      | limit     | `Int`     | `30`                               |
      | reaction  | `String?` | `nil` (optional - filter by emoji) |
    </Tab>

    <Tab title="Success Response">
      **Reactions Array:**

      | Reaction | Reacted By UID      | Reacted By Name | Reacted At   |
      | -------- | ------------------- | --------------- | ------------ |
      | 😴       | `"cometchat-uid-1"` | `"John Doe"`    | `1697025960` |
      | 👍       | `"cometchat-uid-2"` | `"Jane Smith"`  | `1697025950` |
    </Tab>

    <Tab title="Error Response">
      **Object Type:** CometChatException

      | Parameter        | Type     | Value                               |
      | ---------------- | -------- | ----------------------------------- |
      | errorCode        | `String` | `"ERROR_LIMIT_EXCEEDED"`            |
      | errorDescription | `String` | `"Limit Exceeded Max limit of 100"` |
    </Tab>
  </Tabs>
</Accordion>

### Fetch Reactions for Specific Emoji

<Tabs>
  <Tab title="Swift">
    ```swift theme={null}
    let reactionsRequest = ReactionsRequestBuilder()
        .setLimit(limit: 30)
        .setMessageId(messageId: 148)
        .setReaction(reaction: "👍")
        .build()

    reactionsRequest.fetchNext { reactions in
        // Only returns 👍 reactions
    } onError: { error in
        print("Error: \(error?.errorDescription)")
    }
    ```
  </Tab>
</Tabs>

### Fetch Previous Reactions

<Tabs>
  <Tab title="Swift">
    ```swift theme={null}
    reactionsRequest.fetchPrevious { reactions in
        for reaction in reactions {
            print("Reaction: \(reaction.stringValue())")
        }
    } onError: { error in
        print("Error: \(error?.errorDescription)")
    }
    ```
  </Tab>
</Tabs>

***

## Real-time Reaction Events

Keep the chat interactive with real-time updates for reactions.

<Tabs>
  <Tab title="Swift">
    ```swift theme={null}
    let listenerID = "UNIQUE_LISTENER_ID"
    CometChat.addMessageListener(listenerID, self)

    extension YourViewController: CometChatMessageDelegate {
        
        func onMessageReactionAdded(reactionEvent: ReactionEvent) {
            print("Reaction Added")
            print("Reaction: \(reactionEvent.reaction)")
            print("Message ID: \(reactionEvent.reaction.messageId)")
            print("Reacted By: \(reactionEvent.reaction.reactedBy?.name ?? "")")
        }
        
        func onMessageReactionRemoved(reactionEvent: ReactionEvent) {
            print("Reaction Removed")
            print("Reaction: \(reactionEvent.reaction)")
        }
    }

    // Remove listener when done:
    CometChat.removeMessageListener(listenerID)
    ```
  </Tab>
</Tabs>

<Accordion title="Sample Payloads - Reaction Events">
  <Tabs>
    <Tab title="onMessageReactionAdded">
      **Method:** `onMessageReactionAdded(reactionEvent: ReactionEvent)`

      **ReactionEvent Object:**

      | Parameter       | Type           | Description                     |
      | --------------- | -------------- | ------------------------------- |
      | reaction        | `Reaction`     | The reaction details            |
      | receiverId      | `String`       | ID of the receiver              |
      | receiverType    | `ReceiverType` | `.user` or `.group`             |
      | conversationId  | `String`       | ID of the conversation          |
      | parentMessageId | `Int`          | Parent message ID (for threads) |
    </Tab>

    <Tab title="onMessageReactionRemoved">
      **Method:** `onMessageReactionRemoved(reactionEvent: ReactionEvent)`

      **ReactionEvent Object:**

      | Parameter    | Type           | Description          |
      | ------------ | -------------- | -------------------- |
      | reaction     | `Reaction`     | The reaction details |
      | receiverId   | `String`       | ID of the receiver   |
      | receiverType | `ReceiverType` | `.user` or `.group`  |
    </Tab>
  </Tabs>
</Accordion>

***

## Get Reactions List

To retrieve the list of reactions on a particular message:

<Tabs>
  <Tab title="Swift">
    ```swift theme={null}
    let reactions = message.reactions  // Returns [ReactionCount]
    ```
  </Tab>
</Tabs>

***

## Check if Logged-in User Has Reacted

<Tabs>
  <Tab title="Swift">
    ```swift theme={null}
    for reactionCount in message.reactions {
        print("Reaction: \(reactionCount.reaction)")
        print("Reacted by me: \(reactionCount.reactedByMe)")
    }
    ```
  </Tab>
</Tabs>

***

## Update Message With Reaction Info

When you receive a real-time reaction event, use this method to update the message with the latest reaction information. This keeps your local message state in sync with the server.

### Method Signature

<Tabs>
  <Tab title="Swift">
    ```swift theme={null}
    CometChat.updateMessageWithReactionInfo(
        baseMessage: BaseMessage,
        messageReaction: MessageReaction,
        action: ReactionAction
    ) -> BaseMessage
    ```
  </Tab>
</Tabs>

### Parameters

| Parameter       | Type              | Description                              |
| --------------- | ----------------- | ---------------------------------------- |
| baseMessage     | `BaseMessage`     | The message to update                    |
| messageReaction | `MessageReaction` | Reaction info from event                 |
| action          | `ReactionAction`  | `.REACTION_ADDED` or `.REACTION_REMOVED` |

### ReactionAction Enum Values

| Value               | Description                             |
| ------------------- | --------------------------------------- |
| `.REACTION_ADDED`   | A reaction was added to the message     |
| `.REACTION_REMOVED` | A reaction was removed from the message |

### Usage Example - Reaction Added

<Tabs>
  <Tab title="Swift">
    ```swift theme={null}
    extension YourViewController: CometChatMessageDelegate {
        
        func onMessageReactionAdded(reactionEvent: ReactionEvent) {
            // Get the message from your local list
            var message: BaseMessage = getMessageFromList(reactionEvent.reaction.messageId)
            
            // Get the reaction from the event
            let messageReaction: MessageReaction = reactionEvent.reaction
            
            // Update the message with new reaction info
            let modifiedMessage = CometChat.updateMessageWithReactionInfo(
                baseMessage: message,
                messageReaction: messageReaction,
                action: .REACTION_ADDED
            )
            
            // Update your UI with the modified message
            updateMessageInList(modifiedMessage)
        }
    }
    ```
  </Tab>
</Tabs>

### Usage Example - Reaction Removed

<Tabs>
  <Tab title="Swift">
    ```swift theme={null}
    extension YourViewController: CometChatMessageDelegate {
        
        func onMessageReactionRemoved(reactionEvent: ReactionEvent) {
            // Get the message from your local list
            var message: BaseMessage = getMessageFromList(reactionEvent.reaction.messageId)
            
            // Get the reaction from the event
            let messageReaction: MessageReaction = reactionEvent.reaction
            
            // Update the message with removed reaction info
            let modifiedMessage = CometChat.updateMessageWithReactionInfo(
                baseMessage: message,
                messageReaction: messageReaction,
                action: .REACTION_REMOVED
            )
            
            // Update your UI with the modified message
            updateMessageInList(modifiedMessage)
        }
    }
    ```
  </Tab>
</Tabs>

### Complete Real-Time Handling Example

<Tabs>
  <Tab title="Swift">
    ```swift theme={null}
    class ChatViewController: UIViewController, CometChatMessageDelegate {
        
        var messages: [BaseMessage] = []
        
        override func viewDidLoad() {
            super.viewDidLoad()
            CometChat.addMessageListener("reaction-listener", self)
        }
        
        func onMessageReactionAdded(reactionEvent: ReactionEvent) {
            handleReactionEvent(reactionEvent, action: .REACTION_ADDED)
        }
        
        func onMessageReactionRemoved(reactionEvent: ReactionEvent) {
            handleReactionEvent(reactionEvent, action: .REACTION_REMOVED)
        }
        
        private func handleReactionEvent(_ event: ReactionEvent, action: ReactionAction) {
            let messageId = event.reaction.messageId
            
            // Find the message in local list
            guard let index = messages.firstIndex(where: { $0.id == messageId }) else {
                return
            }
            
            // Update message with reaction info
            let updatedMessage = CometChat.updateMessageWithReactionInfo(
                baseMessage: messages[index],
                messageReaction: event.reaction,
                action: action
            )
            
            // Replace in list and refresh UI
            messages[index] = updatedMessage
            tableView.reloadRows(at: [IndexPath(row: index, section: 0)], with: .none)
        }
        
        deinit {
            CometChat.removeMessageListener("reaction-listener")
        }
    }
    ```
  </Tab>
</Tabs>

<Accordion title="Sample Payloads - Update Message With Reaction Info">
  <Tabs>
    <Tab title="Return Value">
      The method returns a `BaseMessage` with updated reactions array:

      | Property  | Type              | Description                     |
      | --------- | ----------------- | ------------------------------- |
      | reactions | `[ReactionCount]` | Updated list of reaction counts |

      **Each ReactionCount contains:**

      | Property    | Type     | Description                  |
      | ----------- | -------- | ---------------------------- |
      | reaction    | `String` | The emoji reaction           |
      | count       | `Int`    | Total count of this reaction |
      | reactedByMe | `Bool`   | If logged-in user reacted    |
    </Tab>
  </Tabs>
</Accordion>

<Note>
  **Notes:**

  * This is a synchronous method - no callbacks needed
  * Always use this method to keep local message state in sync
  * The returned message has updated reactions array
  * Works with both user and group messages
  * Handle both `REACTION_ADDED` and `REACTION_REMOVED` events
</Note>

***

## ReactionCount Object Properties

| Property      | Type     | Description                    |
| ------------- | -------- | ------------------------------ |
| `reaction`    | `String` | The reaction emoji             |
| `count`       | `Int`    | Number of users who reacted    |
| `reactedByMe` | `Bool`   | Whether logged-in user reacted |

***

## MessageReaction Object Properties

| Property    | Type     | Description                 |
| ----------- | -------- | --------------------------- |
| `reaction`  | `String` | The reaction emoji          |
| `reactedBy` | `User?`  | User who added the reaction |
| `reactedAt` | `Double` | Unix timestamp when reacted |
| `messageId` | `Int`    | ID of the message           |

***

## ReactionEvent Object Properties

| Property          | Type           | Description                     |
| ----------------- | -------------- | ------------------------------- |
| `reaction`        | `Reaction`     | The reaction details            |
| `receiverId`      | `String`       | ID of the receiver              |
| `receiverType`    | `ReceiverType` | `.user` or `.group`             |
| `conversationId`  | `String`       | ID of the conversation          |
| `parentMessageId` | `Int`          | Parent message ID (for threads) |

***

## Common Error Codes

| Error Code               | Description                | Resolution          |
| ------------------------ | -------------------------- | ------------------- |
| `ERR_MESSAGE_NOT_FOUND`  | Message doesn't exist      | Verify message ID   |
| `ERR_INVALID_REACTION`   | Invalid reaction emoji     | Use valid emoji     |
| `ERR_ALREADY_REACTED`    | Already reacted with emoji | Remove first        |
| `ERR_REACTION_NOT_FOUND` | Reaction not on message    | User hasn't reacted |
