Skip to content

React Adapter (`@roomful/react`)

Audience: users.

import { RoomfulProvider } from '@roomful/react';
function App() {
return (
<RoomfulProvider
roomId="my-room"
transport="auto"
presence={{ name: 'Alice', color: '#4F46E5' }}
onConnect={() => console.log('connected')}
onError={(error) => console.error(error)}
>
<Workspace />
</RoomfulProvider>
);
}
HookReturnsPurpose
useRoom()Roomaccess low-level room instance
usePresence(){ self, others, all }reactive participant data
useCursors(){ ref, cursors, mount, unmount }cursor tracking/rendering
useSharedState(key, opts)[value, setValue]synchronized state
useAwareness(){ set, setFocus, setSelection, setTyping, others }ephemeral peer context
useEvent(name, handler)emit functionsubscribe and emit
usePeers()Peer[]connected peers
useConnectionStatus()RoomStatuscurrent room status
HookReturnsPurpose
useViewport(opts?){ ref, states, broadcast, stopBroadcast, present, stopPresenting, follow, unfollow }follow a peer’s scroll/zoom (viewport)
useLocks(){ locks, acquire, release, releaseAll, isLocked, getHolder }advisory locks over UI keys (locks)
useLockState(key)LockState | nullone key’s holder, for lock-on-focus (locks)
usePointer(opts?){ ref, beams, activate, deactivate, render }laser pointer beams (pointer)
useComments(opts?){ threads, add, reply, resolve, reopen, getByElement, getOpen }anchored comment threads (comments)
useActivity(opts?){ entries, record }room activity feed (activity)
useFieldPresence(){ fields, setActiveField, getFieldPeers }who’s on which field (field presence)
useAgentApprovals(opts?){ proposals, pending, approve, reject, propose }human-in-the-loop agent approvals (agent approvals)
useSessionSummarizer(opts?)SessionSummarysession rollup from the activity feed (session summarizer)
useHistory(opts?){ timeline, canUndo, canRedo, capture, transaction, undo, redo }undo/redo plus shared timeline (history)

useSharedState(key, opts) intentionally mirrors React useState: it returns a [value, setValue] tuple, and setValue accepts either the next value or an updater function.

import { useCursors, useSharedState } from '@roomful/react';
function PollWidget() {
const { ref, cursors } = useCursors<{ tool: 'pen' | 'eraser' }>();
const [votes, setVotes] = useSharedState('poll-votes', {
initialValue: { yes: 0, no: 0 },
strategy: 'crdt',
});
return (
<div ref={ref}>
<p>
Yes: {votes.yes} | No: {votes.no}
</p>
<p>Remote cursors: {cursors.length}</p>
<button onClick={() => setVotes((v) => ({ ...v, yes: v.yes + 1 }))}>Vote Yes</button>
</div>
);
}
  • useSharedState() currently binds one shared-state engine per room. Every component in that room must use the same key.
  • opts forwards directly to room.useState(...), including initialValue, strategy, and persist.
  • The setter reference is stable across rerenders and room replacement.