Most collaborative features rely on each user having their own temporary state, which is then shared with others. For example, in an app using multiplayer cursors, the location of each user’s cursor will be their state. This state could also be used for a typing indicator, or to show a user’s current selection. In Liveblocks, we call this presence.
We can use presence to hold any object that we wish to share with others. An example would be the coordinates of a user’s cursor on screen:
cursor: { x: 256, y: 367 }
To start using presence, let’s define a type for it in liveblocks.config.ts
.
We’ll use the format above for displaying cursors, with the addition of null
to represent an off-screen cursor.
/liveblocks.config.ts
// Presence typetype Presence = { cursor: { x: number; y: number } | null;};
You’ll notice that at the bottom of the file, we’ve already added Presence
to
createRoomContext
. Because we’re exporting our hooks from here, all our types
will automatically propagate through our entire app.
The last step in setting up presence is setting an initial value. Switch to
App.tsx
and pass cursor: null
to RoomProvider
—no one starts with
their cursor on-screen.
/App.tsx
<RoomProvider id={roomId} initialPresence={{ cursor: null }}>
To display the current user’s presence, we’ll add useMyPresence
to
Room.tsx
, and quickly display its value, similarly to useState
.
/Room.tsx
import { useMyPresence } from "./liveblocks.config";
export function Room() { const [myPresence, updateMyPresence] = useMyPresence();
return <div>Cursor: {JSON.stringify(myPresence.cursor)}</div>;}
Great! Press the refresh button in the preview window to reload
initialPresence
, and you should now be seeing Cursor: null
! On the next page
we’ll be creating live cursors with presence.