# 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://sdk.ably.com/builds/ably/ably-chat-js/main/typedoc/interfaces/chat-js.RoomReactions.html#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}")
}
```
```jetpack
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` |
### 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://sdk.ably.com/builds/ably/ably-chat-js/main/typedoc/interfaces/chat-js.RoomReactions.html#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 (