React Flow
This is an example of real-time collaborative React Flow.
App.tsx
1import { useCallback } from 'react';2import { JSONArray, JSONObject, useDocument } from '@yorkie-js/react';3import {4 ReactFlow,5 Controls,6 MiniMap,7 Node,8 Edge,9 Background,10 NodeChange,11 EdgeChange,12} from '@xyflow/react';13import '@xyflow/react/dist/style.css';14import './App.css';1516type Graph = {17 nodes: JSONArray<JSONObject<Node>>;18 edges: JSONArray<JSONObject<Edge>>;19};2021function App() {22 const { root, update, loading, error } = useDocument<Graph>();2324 const onNodesChange = useCallback(25 (changes: Array<NodeChange>) => {26 update((r) => {27 for (const c of changes) {28 switch (c.type) {29 case 'add':30 r.nodes.push(c.item);31 break;32 case 'replace':33 {34 const idx = r.nodes.findIndex((n) => n.id === c.id);35 r.nodes[idx] = c.item;36 }37 break;38 case 'remove':39 {40 const idx = r.nodes.findIndex((n) => n.id === c.id);41 r.nodes.deleteByID!(r.nodes[idx].getID!());42 }43 break;44 case 'position':45 {46 const idx = r.nodes.findIndex((n) => n.id === c.id);47 r.nodes[idx].position = c.position!;48 }49 break;50 case 'select':51 {52 const idx = r.nodes.findIndex((n) => n.id === c.id);53 r.nodes[idx].selected = c.selected;54 }55 break;56 default:57 break;58 }59 }60 });61 },62 [update],63 );6465 const onEdgesChange = useCallback(66 (changes: Array<EdgeChange>) => {67 update((r) => {68 for (const c of changes) {69 switch (c.type) {70 case 'add':71 r.edges.push(c.item);72 break;73 case 'replace':74 {75 const idx = r.edges.findIndex((e) => e.id === c.id);76 r.edges[idx] = c.item;77 }78 break;79 case 'remove':80 {81 const idx = r.edges.findIndex((e) => e.id === c.id);82 r.edges.deleteByID!(r.edges[idx].getID!());83 }84 break;85 case 'select':86 {87 const idx = r.edges.findIndex((e) => e.id === c.id);88 r.edges[idx].selected = c.selected;89 }90 break;91 default:92 break;93 }94 }95 });96 },97 [update],98 );99100 if (loading) return <div>Loading...</div>;101 if (error) return <div>Error: {error.message}</div>;102103 return (104 <div style={{ position: 'fixed', inset: 0, height: '100vh' }}>105 <ReactFlow106 nodes={root.nodes}107 edges={root.edges}108 onNodesChange={onNodesChange}109 onEdgesChange={onEdgesChange}110 fitView111 >112 <Background gap={10} size={1} color="silver" />113 <Controls orientation="horizontal" showInteractive={false} />114 <MiniMap />115 </ReactFlow>116 </div>117 );118}119120export default App;
- User 1
- User 2
- User 1
- User 2
Event Log