Skip to main content

Members (Presence)

Beta

This feature is in beta. Core behavior is stable, but some APIs or configuration may change before general availability.

room.members is the presence layer of Room.

It tells you who is currently in the room and lets each member publish lightweight ephemeral state such as typing, cursor position, or hand raise status.

Client Surface

Assume room is an authenticated room client created with client.room(...).

room.members.onSync((members) => renderRoster(members));
room.members.onJoin((member) => notifyJoin(member));
room.members.onLeave((member, reason) => notifyLeave(member, reason));

await room.members.setState({ typing: true, cursor: { x: 10, y: 20 } });
await room.members.clearState();

The main client APIs are:

  • room.members.list()
  • room.members.onSync(...)
  • room.members.onJoin(...)
  • room.members.onLeave(...)
  • room.members.setState(...)
  • room.members.clearState()
  • room.members.onStateChange(...)

Member Semantics

  • A public member is user-oriented, not raw-connection-oriented.
  • connectionId still exists when needed for diagnostics or metadata.
  • connectionCount lets you distinguish one user on multiple tabs or devices.

Typical leave reasons are:

  • leave
  • disconnect
  • kicked

Server Hooks

Room exposes member-specific hooks so you can mirror presence into metadata or analytics without mixing it into authoritative state.

rooms: {
collab: {
hooks: {
members: {
onJoin: (member, room) => {
room.setMetadata({ ...room.getMetadata(), lastMemberJoin: member.memberId });
},
onStateChange: (member, state, room) => {
room.setMetadata({
...room.getMetadata(),
lastPresenceUpdate: { memberId: member.memberId, state },
});
},
},
},
},
}

Members vs State

  • Use State for source-of-truth gameplay or collaborative data.
  • Use members for ephemeral presence information that should disappear when users leave.

Session Interaction

Reconnect behavior affects membership:

  • a disconnect can temporarily keep a member in the room during the reconnect grace period
  • hooks.session.onReconnect(...) and hooks.session.onDisconnectTimeout(...) let you observe that lifecycle

See Advanced for reconnect timing details.