# Room reactions Users can send reactions to the entire chat room to show their sentiment as to what is happening. For example, agreeing with the content in a livestream using a thumbs up, or sending a heart when their team scores in a sports game. Room reactions are ephemeral and not stored or aggregated by Ably. The intention being that they show the overall sentiment of a room at a point in time. ## Subscribe to room reactions Subscribe to room reactions by registering a listener. Use the [`reactions.subscribe()`](https://ably.com/docs/chat/api/javascript/room-reactions.md?source=llms.txt#subscribe)[`reactions.subscribe()`](https://sdk.ably.com/builds/ably/ably-chat-swift/main/AblyChat/documentation/ablychat/roomreactions/subscribe%28%29-64gdf)[`reactions.subscribe()`](https://sdk.ably.com/builds/ably/ably-chat-kotlin/main/dokka/chat/com.ably.chat/-room-reactions/subscribe.html) method in a room to receive reactions: Use the [`reactions.asFlow()`](https://sdk.ably.com/builds/ably/ably-chat-kotlin/main/dokka/chat/com.ably.chat/as-flow.html) to receive new room reactions: Subscribe to room reactions with the [`useRoomReactions`](https://sdk.ably.com/builds/ably/ably-chat-js/main/typedoc/functions/chat-react.useRoomReactions.html) hook. Supply an optional listener to receive the room reactions. ### Javascript ``` const {unsubscribe} = room.reactions.subscribe((event) => { const reaction = event.reaction; console.log(`Received a reaction from ${reaction.clientId} with name ${reaction.name}, and metadata ${reaction.metadata}`); }); ``` ### React ``` import React from 'react'; import { useRoomReactions } from '@ably/chat/react'; const MyComponent = () => { useRoomReactions({ listener: (reactionEvent) => { console.log('Received reaction: ', reactionEvent.reaction); }, }); return
Room Reactions Component
; }; ``` ### Swift ``` let reactionSubscription = room.reactions.subscribe() for await event in reactionSubscription { print("Received a reaction of name \(event.reaction.name), and metadata \(event.reaction.metadata)") } ``` ### Kotlin ``` val subscription = room.reactions.subscribe { event: RoomReactionEvent -> println("Received a reaction of name ${event.reaction.name} with metadata ${event.reaction.metadata}") } ``` ### Android ``` import androidx.compose.runtime.* import com.ably.chat.Room import com.ably.chat.RoomReactionEvent @Composable fun RoomReactionsComponent(room: Room) { LaunchedEffect(room) { room.reactions.asFlow().collect { event: RoomReactionEvent -> println("Received a reaction of name ${event.reaction.name} with metadata ${event.reaction.metadata}") } } } ```
### Room reaction event structure The following are the properties of a room reaction event: | Property | Description | Type | | -------- | ----------- | ---- | | `type` | The type of reaction event. | `String` | | `reaction` | The reaction data. | `Object` | | `reaction.name` | The name of the reaction, for example a 'like' or a heart emoji. | `String` | | `reaction.headers` | Optional headers for adding additional information to a reaction. | `Object` | | `reaction.metadata` | Optional metadata about the reaction, such as an animation or effect. This information is not read by Ably. | `Object` | | `reaction.createdAt` | The time the reaction was sent. | `Date` | | `reaction.clientId` | The client identifier of the user that sent the reaction. | `String` | | `reaction.isSelf` | Will be `true` for the user that sent the reaction. | `Boolean` | | `reaction.userClaim` | A server-signed [user claim](https://ably.com/docs/chat/setup.md?source=llms.txt#user-claims) attached to this reaction, derived from the user's [JWT](https://ably.com/docs/chat/setup.md?source=llms.txt#set-user-claims). | `String` (optional) | ### Unsubscribe from room reactions Use the `unsubscribe()` function returned in the `subscribe()` response to remove a room reaction listener: Jetpack Compose automatically handles lifecycle and cleanup when using `LaunchedEffect` with `asFlow`. You don't need to handle removing listeners, as this is done automatically by the SDK. When you unmount the component that is using the `useRoomReactions` hook, it will automatically handle unsubscribing any associated listeners registered for room reactions. #### Javascript ``` // Initial subscription const {unsubscribe} = room.reactions.subscribe((event) => { console.log(`Received a reaction of type ${event.reaction.name}, and metadata ${event.reaction.metadata}`); }); // To remove the listener unsubscribe(); ``` #### Kotlin ``` // Initial subscription val (unsubscribe) = room.reactions.subscribe { event -> println("Received a reaction of type ${event.reaction.name}, and metadata ${event.reaction.metadata}") } // To remove the listener unsubscribe() ``` ## Send a room reaction Use the [`reactions.send()`](https://ably.com/docs/chat/api/javascript/room-reactions.md?source=llms.txt#send)[`reactions.send()`](https://sdk.ably.com/builds/ably/ably-chat-swift/main/AblyChat/documentation/ablychat/roomreactions/send%28withparams%3A%29)[`reactions.send()`](https://sdk.ably.com/builds/ably/ably-chat-kotlin/main/dokka/chat/com.ably.chat/-room-reactions/send.html) method to send a room-level reaction. The most common way of using this method is to trigger it whenever a user clicks an emoji button in a room: Use the [`sendRoomReaction()`](https://sdk.ably.com/builds/ably/ably-chat-js/main/typedoc/interfaces/chat-react.UseRoomReactionsResponse.html#sendroomreaction) method available from the response of the `useRoomReactions` hook to emit an event when a user reacts, for example when they click an emoji button: ### Javascript ``` await room.reactions.send({name: "like"}); await room.reactions.send({name: "heart", metadata: {"effect": "fireworks"}}); ``` ### React ``` import { useRoomReactions } from '@ably/chat/react'; const MyComponent = () => { const { sendRoomReaction } = useRoomReactions(); const sendLike = () => { sendRoomReaction({ name: 'like' }); }; return (
); }; ``` ### Swift ``` try await room.reactions.send(params: .init(name: "like")) try await room.reactions.send(params: .init(name: "heart", metadata: ["effect": "fireworks"])) ``` ### Kotlin ``` room.reactions.send(name = "like") // import com.ably.chat.json.* room.reactions.send(name = "heart", metadata = jsonObject { put("effect", "fireworks") }) ``` ### Android ``` import androidx.compose.material.* import androidx.compose.runtime.* import com.ably.chat.Room import com.ably.chat.json.* import kotlinx.coroutines.launch @Composable fun SendReactionComponent(room: Room) { val coroutineScope = rememberCoroutineScope() Button(onClick = { coroutineScope.launch { room.reactions.send(name = "like") } }) { Text("Send Like") } Button(onClick = { coroutineScope.launch { room.reactions.send( name = "heart", metadata = jsonObject { put("effect", "fireworks") } ) } }) { Text("Send Heart with Effect") } } ```
## Related Topics - [Messages](https://ably.com/docs/chat/rooms/messages.md?source=llms.txt): Send, update, delete, and receive messages in chat rooms. - [Message history](https://ably.com/docs/chat/rooms/history.md?source=llms.txt): Retrieve previously sent messages from history. - [Presence](https://ably.com/docs/chat/rooms/presence.md?source=llms.txt): Use presence to see which users are online and their user status. - [Occupancy](https://ably.com/docs/chat/rooms/occupancy.md?source=llms.txt): Use occupancy to see how many users are in a room. - [Message reactions](https://ably.com/docs/chat/rooms/message-reactions.md?source=llms.txt): React to chat messages - [Typing indicators](https://ably.com/docs/chat/rooms/typing.md?source=llms.txt): Display typing indicators in a room so that users can see when someone else is writing a message. - [Share media](https://ably.com/docs/chat/rooms/media.md?source=llms.txt): Share media such as images, videos, or files in a chat room. - [Message replies](https://ably.com/docs/chat/rooms/replies.md?source=llms.txt): Add reply functionality to messages in a chat room. ## Documentation Index To discover additional Ably documentation: 1. Fetch [llms.txt](https://ably.com/llms.txt?source=llms.txt) for the canonical list of available pages. 2. Identify relevant URLs from that index. 3. Fetch target pages as needed. Avoid using assumed or outdated documentation paths.