GitHub

React Hooks

vuer-rtc provides React hooks for seamless integration with React applications.

Installation

The hooks are available from the /hooks subpath:

import { GraphProvider, useGraph, useNode, useGraphActions } from '@vuer-ai/vuer-rtc/hooks';

GraphProvider

Wrap your app with GraphProvider to provide the graph context:

function App() {
  return (
    <GraphProvider sessionId="my-session" onSend={sendToServer}>
      <Scene />
    </GraphProvider>
  );
}

Props

PropTypeDescription
sessionIdstringUnique session identifier
onSend(msg: CRDTMessage) => voidCallback when a message is ready to send

useGraph

Get the current graph state:

function Scene() {
  const graph = useGraph();
  return (
    <>
      {Object.keys(graph.nodes).map(key => (
        <Node key={key} nodeKey={key} />
      ))}
    </>
  );
}

useNode

Subscribe to a specific node by key. Re-renders only when that node changes:

function Node({ nodeKey }: { nodeKey: string }) {
  const node = useNode(nodeKey);

  if (!node) return null;

  return (
    <mesh position={node.position}>
      <boxGeometry />
    </mesh>
  );
}

useGraphActions

Get actions to modify the graph:

function Node({ nodeKey }: { nodeKey: string }) {
  const node = useNode(nodeKey);
  const { edit, commit, undo, redo } = useGraphActions();

  const onDrag = (delta: [number, number, number]) => {
    edit({ otype: 'vector3.add', key: nodeKey, path: 'position', value: delta });
  };

  const onDragEnd = () => {
    commit(`Move ${node?.name}`);
  };

  if (!node) return null;
  return <mesh position={node.position} onDrag={onDrag} onDragEnd={onDragEnd} />;
}

Available Actions

ActionSignatureDescription
edit(op: Operation) => voidAdd operation to edit buffer (uncommitted)
commit(description?: string) => voidCommit edits as a single message
cancelEdits() => voidDiscard uncommitted edits
undo() => voidUndo last committed message
redo() => voidRedo last undone message
receive(msg: CRDTMessage) => voidProcess incoming remote message

Full Example

import { GraphProvider, useGraph, useNode, useGraphActions } from '@vuer-ai/vuer-rtc/hooks';

function App() {
  const wsRef = useRef<WebSocket | null>(null);

  const handleSend = (msg: CRDTMessage) => {
    wsRef.current?.send(JSON.stringify(msg));
  };

  return (
    <GraphProvider sessionId="user-123" onSend={handleSend}>
      <Canvas>
        <Scene />
      </Canvas>
      <UndoRedoButtons />
    </GraphProvider>
  );
}

function Scene() {
  const graph = useGraph();
  const { receive } = useGraphActions();

  // Handle incoming messages
  useEffect(() => {
    const ws = new WebSocket('wss://server/room');
    ws.onmessage = (e) => receive(JSON.parse(e.data));
    return () => ws.close();
  }, [receive]);

  return (
    <>
      {Object.keys(graph.nodes)
        .filter(k => !graph.nodes[k].deletedAt)
        .map(key => <Node key={key} nodeKey={key} />)}
    </>
  );
}

function UndoRedoButtons() {
  const { undo, redo } = useGraphActions();
  return (
    <div>
      <button onClick={undo}>Undo</button>
      <button onClick={redo}>Redo</button>
    </div>
  );
}