React Adapter (`@roomful/react`)
Audience: users.
Provider
Section titled “Provider”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> );}| Hook | Returns | Purpose |
|---|---|---|
useRoom() | Room | access 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 function | subscribe and emit |
usePeers() | Peer[] | connected peers |
useConnectionStatus() | RoomStatus | current room status |
useSharedState(key, opts) intentionally mirrors React useState: it returns a [value, setValue] tuple, and setValue accepts either the next value or an updater function.
Example
Section titled “Example”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> );}Shared State Notes
Section titled “Shared State Notes”useSharedState()currently binds one shared-state engine per room. Every component in that room must use the samekey.optsforwards directly toroom.useState(...), includinginitialValue,strategy, andpersist.- The setter reference is stable across rerenders and room replacement.