```javascript
const { unsubscribe } = room.presence.subscribe((event) => {
console.log(`Presence event ${event.type} from ${event.member.clientId} with data ${event.member.data}`);
});
```
```react
const MyComponent = () => {
const { presenceData, error } = usePresenceListener({
listener: (event) => {
console.log('Presence event: ', event);
},
});
return (
Presence data:
{error === undefined ? (
{presenceData.map((presence) => (
- {presence.clientId}
))}
) : (
Error loading presence data
)}
);
};
```
```swift
let presenceSubscription = room.presence.subscribe()
for await event in presenceSubscription {
print("Presence event `\(event.type)` from `\(event.member.clientId)` with data `\(event.member.data)`")
}
```
```kotlin
const MyComponent = () => {
// This data is only relevant when auto-entry is enabled
// Once it has been used once, subsequent changes will have no effect
const presenceParams = {
initialData: { status: 'Online' },
};
// By default, presence will be entered when the hook mounts and left
// when it subsequently unmounts.
const { isPresent } = usePresence(presenceParams);
return (
Presence status: {isPresent ? 'Online' : 'Offline'}
);
};
```
```swift
try await room.presence.enter(withData: ["status": "Online"])
```
```kotlin
// import com.ably.chat.json.*
room.presence.enter(
jsonObject {
put("status", "Online")
},
)
```
```jetpack
const MyComponent = () => {
const presenceParams = {
initialData: { status: 'Online' },
};
const { update, isPresent } = usePresence(presenceParams);
const updatePresence = () => {
update({ status: 'Away' });
};
return (
Presence status: {isPresent ? 'Online' : 'Offline'}
);
};
```
```swift
try await room.presence.update(withData: ["status": "Busy"])
```
```kotlin
// import com.ably.chat.json.*
room.presence.update(
jsonObject {
put("status", "Busy")
},
)
```
```jetpack
const MyComponent = () => {
const presenceParams = {
initialData: { status: 'Online' },
};
// Call leave explicitly to disable auto-entry and leave presence
const { isPresent, leave } = usePresence(presenceParams);
return (
Presence status: {isPresent ? 'Online' : 'Offline'}
);
};
```
```swift
try await room.presence.leave(withData: ["status": "Be back later!"])
```
```kotlin
// import com.ably.chat.json.*
room.presence.leave(
jsonObject {
put("status", "Be back later!")
},
)
```
```jetpack
import { usePresence } from '@ably/chat/react';
const MyComponent = () => {
// Mount the hook without auto-entry
const presenceParams = {
autoEnterLeave: false,
};
const { isPresent, leave, enter, update } = usePresence(presenceParams);
// Manual mount behavior - enter presence when component mounts
useEffect(() => {
enter({ status: 'active' });
// Manual unmount behavior - leave presence when component unmounts
return () => {
leave({ status: 'disconnecting' });
};
}, [enter, leave]);
// Update presence data when some event happens
const onSomeEvent = useCallback(() => {
const now = Date.now();
update({status: 'active', updated: now});
}, [update]);
return (
Presence status: {isPresent ? 'Online' : 'Offline'}
);
};
```
### Multiple Presence Data Contributors
Using multiple instances of `usePresence` with `autoEnterLeave` set to `true` is not recommended as the hooks maintain internal state to manage this behavior that is not shared between hooks. Furthermore, all instances of the hook use the same underlying presence instances, so calls to `enter`, `update` and `leave` can interact in unintended ways and lead to race conditions. Furthermore, the calls are PUT-like operations that replace your entire presence data payload. If you have multiple areas of your application that contribute data to presence, you can achieve this by using a central place to store your presence data.
To implement this pattern, you would define a Provider or Context further up your application tree, or using a global state store such as Redux. Individual areas of your codebase then update this value (or contribute to parts of it). A single call to `usePresence` can then be used to keep this state synchronized with presence whenever the value changes. This allows multiple distinct components to contribute to the presence data, without multiple calls to `usePresence` and importantly, without requiring them to know anything about the complete presence data.
## Presence options
The following options can be set when [creating a room](https://ably.com/docs/chat/rooms#create) that are specific to presence:
| Property | Description | Default |
| --- | --- | --- |
| enableEvents | Set whether the client has permissions to subscribe to the presence set. Calling `presence.subscribe()` is still required. | true |
## Retrieve the presence set
```javascript
// Retrieve all users entered into presence as an array:
const presentMembers = await room.presence.get();
// Retrieve the status of specific users by their clientId:
const presentMember = await room.presence.get({ clientId: 'clemons123' });
```
```swift
// Retrieve all users entered into presence as an array:
let presentMembers = try await room.presence.get()
// Retrieve the status of specific users by their clientId:
let presentMember = try await room.presence.get(withParams: .init(clientID: "clemons123"))
```
```kotlin
// Retrieve all users entered into presence as an array:
val presentMembers = room.presence.get()
// Retrieve the status of specific users by their clientId:
val presentMember = room.presence.get(clientId = "clemons123")
```
```jetpack
// Retrieve all users entered into presence as an array:
val presentMembers = room.presence.get()
// Retrieve the status of specific users by their clientId:
val presentMember = room.presence.get(clientId = "clemons123")
```
Alternatively, use the
```javascript
const isPresent = await room.presence.isUserPresent('clemons123');
```
```swift
let isPresent = try await room.presence.isUserPresent(withClientID: "clemons123")
```
```kotlin
val isPresent = room.presence.isUserPresent("client-id")
```
```jetpack
val isPresent = room.presence.isUserPresent("client-id")
```