Implement and manage presence/awareness using Yjs in any React application using two simple React hooks: useSelf
and useUsers
.
For all the demos, you can open a new tab on your browser to observe how the presence updates in each example.
yarn add y-presence
# or
npm i y-presence
// src/store.ts
import { WebsocketProvider } from "y-websocket";
import { Doc } from "yjs";
// Create the shared doc (from Yjs)
const doc = new Doc();
// Create a provider
const provider = new WebsocketProvider(
"wss://demos.yjs.dev",
"y-presence-demo",
doc
);
// Get the provider's awareness API
export const awareness = provider.awareness;
// Set the local awareness state
awareness.setLocalState({ name: "John Doe", email: "johndoe@gmail.com" });
// src/App.tsx
import { useUsers } from "y-presence";
import { awareness } from "./store.ts";
export default function App() {
// Fetch all users connected in the room
const users = useSelf(awareness);
return <div>Number of connected users: {users.size}</div>;
}
The useUsers
hook subscribes to updates to the awareness states of all users connected in the room. It accepts three arguments:
- An awareness object returned by connection provider.
- (Optional) A selector function that accepts a map of the awareness states and enables selecting a subset of this map. This signals React to rerender the component only when this subset has changed.
- (Optional) A equality function to detect if the selected subset has changed.
// Returns a map of the client id to their awareness state and rerenders when any such awareness state changes
const users = useUsers(awareness);
// equivalent to:
const users = useUsers(awareness, (state) => state);
// Map {
// 3965141439 => { name: "John Doe", email: "johndoe@gmail.com" }
// }
// Returns the number of users connected in the room and rerenders when this number changes
const size = useUsers(awareness, (state) => state.size);
// 1
// Returns the awareness state of the current user (self) and rerenders when this state changes. A simpler/optimized hook for this use case is also provided, and is discussed below:
const self = useUsers(awareness, (state) => state.get(awareness.clientId));
// {
// name: "John Doe",
// email: "johndoe@gmail.com"
// }
The useSelf
hook subscribes to updates to the awareness state of the current user (self) in the room. It accepts three arguments:
- An awareness object returned by connection provider.
- (Optional) A selector function that accepts an awareness state object and enables selecting a subset of this object. This signals React to rerender the component only when this subset has changed.
- (Optional) A equality function to detect if the selected subset has changed.
// Returns the awareness state of the current user (self) and rerenders when this state changes.
const self = useSelf(awareness);
// is equivalent to:
const self = useSelf(awareness, (state) => state);
// {
// name: "John Doe",
// email: "johndoe@gmail.com"
// }
// Returns the value of the property `name` of the current user's awareness state and rerenders when this value changes
const name = useSelf(awareness, (state) => state?.name);
// "John Doe"
This project is licensed under MIT.
The two hooks are inspired by the Liveblocks' Presence hooks. Check out their website and documentation to learn more about their presence/awareness implementation.