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

# Reactions

> Add, remove, and fetch message reactions in real-time using the CometChat iOS SDK. Includes listener events and helper methods for updating UI.

<Accordion title="AI Integration Quick Reference">
  ```swift theme={null}
  // Add a reaction
  CometChat.addReaction(messageId: 148, reaction: "\u{1F60A}") { msg in } onError: { err in }

  // Remove a reaction
  CometChat.removeReaction(messageId: 148, reaction: "\u{1F60A}") { msg in } onError: { err in }

  // Fetch reactions for a message
  let request = ReactionsRequestBuilder().setMessageId(messageId: 148).setLimit(limit: 10).build()
  request.fetchNext { reactions in } onError: { error in }

  // Listen for reaction events (CometChatMessageDelegate)
  func onMessageReactionAdded(reactionEvent: ReactionEvent) { }
  func onMessageReactionRemoved(reactionEvent: ReactionEvent) { }
  ```
</Accordion>

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>

<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.

Both `addReaction()` and `removeReaction()` return a [`BaseMessage`](/sdk/reference/messages#basemessage) object with the updated reactions.

<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>

***

## 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>

### 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>

***

## Get Reactions List

To retrieve the list of reactions on a particular message. Returns an array of [`ReactionCount`](/sdk/reference/auxiliary#reactioncount) objects:

<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`](/sdk/reference/messages#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>

<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`](/sdk/reference/entities#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 |

***

## Next Steps

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

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

  <Card title="Mentions" icon="at" href="/sdk/ios/mentions">
    Mention specific users in messages
  </Card>

  <Card title="Threaded Messages" icon="comments" href="/sdk/ios/threaded-messages">
    Organize conversations with message threads
  </Card>
</CardGroup>
