Skip to content

Your first React graph ​

Render three service dependencies with the Graph component. React handles mounting and cleanup; your application owns the data.

Expected result: three blue nodes in a circle, with arrows from Gateway to Orders and from Orders to Database.

Open the live React tutorial

Preview availability

Requires repository access, Node.js 22.13+ and pnpm 11.7.0 for local setup. Packages are not published to npm. Project status.

1. Prepare the workspace ​

Graphora's packages are unpublished. From an authorized checkout, build and run the checked-in React example against the local workspace packages:

bash
cd graph-library
pnpm install --frozen-lockfile
pnpm build
pnpm exec vite examples/react/first-graph \
  --config examples/react/vite.config.ts

2. Render a graph ​

Keep the graph and layout objects stable. Graph treats a new graph reference as a data update and a new layout reference as a runtime configuration change. Defining static values outside the component is the simplest safe pattern.

These snippets come directly from the runnable tutorial, so no copying is required to run it. Keep examples/react/vite.config.ts and inspect examples/react/first-graph/index.html:

html
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Graphora React graph</title>
  </head>
  <body>
    <h1>Service dependencies</h1>
    <div id="root"></div>
    <script type="module" src="/src/main.tsx"></script>
  </body>
</html>

The complete examples/react/first-graph/src/main.tsx:

tsx
import * as React from 'react'
import { createRoot } from 'react-dom/client'

import { createCircularLayout } from '@graphora/layouts'
import { Graph } from '@graphora/react'

import './style.css'

const graph = {
  nodes: [
    { id: 'gateway', label: 'Gateway' },
    { id: 'orders', label: 'Orders' },
    { id: 'database', label: 'Database' }
  ],
  edges: [
    {
      id: 'gateway-orders',
      source: 'gateway',
      target: 'orders',
      directed: true
    },
    {
      id: 'orders-database',
      source: 'orders',
      target: 'database',
      directed: true
    }
  ]
}

const layout = createCircularLayout({ radius: 120 })
const theme = {
  backgroundColor: '#f8fafc',
  node: { fill: '#2563eb', radius: 22 },
  edge: { stroke: '#64748b', strokeWidth: 2, arrow: { end: true } },
  label: { visible: true, fill: '#0f172a', fontSize: 13 }
}

function App(): React.ReactElement {
  return (
    <Graph
      graph={graph}
      layout={layout}
      fitToViewOnLayout={{ padding: 48 }}
      ariaLabel="Service dependency graph"
      className="graph-surface"
      theme={theme}
    />
  )
}

createRoot(document.querySelector('#root') as HTMLElement).render(<App />)

The component enables hover, click selection, node drag, background pan, and wheel zoom by default. It destroys its engine and renderer when React unmounts it.

The container size comes from examples/react/first-graph/src/style.css:

css
html,
body {
  width: 100%;
  height: 100%;
  margin: 0;
}

.graph-surface {
  width: 100%;
  height: 100%;
  min-height: 360px;
}

#graph,
#root {
  height: 360px;
}
body {
  font-family: system-ui, sans-serif;
  background: #f8fafc;
  color: #0f172a;
}
h1 {
  font-size: 1rem;
  margin: 12px 16px;
}

Make your first change ​

In src/main.tsx, change the theme's node fill from #2563eb to #0f766e and save. Vite refreshes the page: all three nodes become teal, while their labels and connections stay the same. This changes the default node color; item styles can override individual nodes.

Your graph should show Gateway → Orders → Database. If the canvas is empty, check the container height and browser console; see blank canvas troubleshooting.

Continue with your own graph ​

Data that changes during rendering ​

Use useMemo when graph or layout values depend on state. Stable identity prevents an unrelated render from reloading data or rebuilding the runtime.

tsx
import * as React from 'react'
import { createRoot } from 'react-dom/client'

import { createCircularLayout } from '@graphora/layouts'
import { Graph } from '@graphora/react'

import './style.css'

const sourceGraph = {
  nodes: [
    { id: 'gateway', label: 'Gateway' },
    { id: 'orders', label: 'Orders' },
    { id: 'database', label: 'Database' }
  ],
  edges: [
    { id: 'go', source: 'gateway', target: 'orders' },
    { id: 'od', source: 'orders', target: 'database' }
  ]
}

function FilterableGraph(): React.ReactElement {
  const [showDatabase, setShowDatabase] = React.useState(true)
  const layout = React.useMemo(() => createCircularLayout({ radius: 120 }), [])
  const graph = React.useMemo(() => {
    const nodes = showDatabase
      ? sourceGraph.nodes
      : sourceGraph.nodes.filter((node) => node.id !== 'database')
    const visibleIds = new Set(nodes.map((node) => node.id))

    return {
      nodes,
      edges: sourceGraph.edges.filter(
        (edge) => visibleIds.has(edge.source) && visibleIds.has(edge.target)
      )
    }
  }, [showDatabase])

  return (
    <>
      <button onClick={() => setShowDatabase((visible) => !visible)}>
        Toggle database
      </button>
      <Graph
        graph={graph}
        layout={layout}
        graphUpdatePolicy="preserve"
        className="graph-surface"
        ariaLabel="Filterable service dependencies"
      />
    </>
  )
}

createRoot(document.querySelector('#root') as HTMLElement).render(
  <FilterableGraph />
)

The default graphUpdatePolicy="relayout" runs the current layout when the graph reference changes. Use graphUpdatePolicy="preserve" for filtering or incremental updates where existing node positions and the camera should survive. Call the ref's clearPositionMemory() before an explicit reset.

Add callbacks and a ref ​

Use controlled selection when another panel also needs to select graph items. The React callbacks example shows onNodeClick, onCanvasClick, onSelectionChange, onReady, and GraphRef. The dependency explorer guide shows a more complete application.

See GraphProps and GraphRef in the React API reference.