Standalone Link Routing
@joint/router-avoid routes every link in the graph around the elements in the way, and re-routes as they move. It is a service attached to the graph, not a router you set on a link - see the core guide for how it works and what it can do. This page is the React setup.
Installation
- npm
- pnpm
- yarn
npm add @joint/router-avoid
pnpm add @joint/router-avoid
yarn add @joint/router-avoid
Setup
initAvoidRouter(graph) needs the graph, so wrap it in a hook and call it from a component inside <GraphProvider>:
import { useEffect } from 'react';
import { useGraph } from '@joint/react';
import { initAvoidRouter, type RouterService } from '@joint/router-avoid';
function useAvoidRouter() {
const { graph } = useGraph();
useEffect(() => {
let router: RouterService | null = null;
let cancelled = false;
async function setup() {
const created = await initAvoidRouter(graph, { shapeBufferDistance: 20 });
if (cancelled) {
created.destroy();
return;
}
router = created;
router.start();
}
setup();
return () => {
cancelled = true;
router?.destroy();
};
}, [graph]);
}
start()attaches the router to the graph. Without it nothing is routed.initAvoidRouteris async (it loads a WebAssembly module). Thecancelledflag handles an unmount before it resolves;destroy()in the cleanup handles one after.- The router writes routes straight onto the links. Nothing to wire on
<Paper>.
Without a hook
If the graph is created outside React anyway, set up the router next to it and pass the graph in:
import { dia, shapes } from '@joint/core';
import { ElementModel, LinkModel, GraphProvider } from '@joint/react';
import { initAvoidRouter } from '@joint/router-avoid';
const graph = new dia.Graph({}, {
cellNamespace: { ...shapes, element: ElementModel, link: LinkModel },
});
graph.resetCells(initialCells);
const router = await initAvoidRouter(graph, { shapeBufferDistance: 20 });
router.start();
<GraphProvider graph={graph}>…</GraphProvider>
The namespace entries let type: 'element' / type: 'link' records resolve on a graph you created yourself.
Ports
Links connected to portMap ports are routed to the port, approaching from the side it sits on. Nothing to configure - source: { id, port } is enough. Drag an element below to see the routes recompute:
The demo points libavoidFilePath at a CDN because the sandbox can't serve the .wasm itself - in your app, serve it from your own bundle.
Large graphs and performance
By default routing runs on the main thread. On a few hundred cells a routing pass takes long enough to block the UI - dragging stutters while the routes are computed. Pass worker to run it in a Web Worker instead and keep the UI responsive. Nothing else changes; destroy() terminates the Worker too.
initAvoidRouter(graph, { worker: { debounceTime: 250 } });
debounceTime is how long the Worker waits after the last change before routing the whole batch at once - raise it when many cells move together.
Your bundler has to emit the package's Worker module - Vite and webpack 5 do, with one Vite dev-server snag; see Running in a Worker. No live demo here, the sandbox can't bundle it.
For a complete React setup - a flowchart of up to 2000 cells routed off the main thread, with a readout of how long each pass took - see the Standalone Link Routing demo in joint-demos.
Going further
Options, events, one-shot routing, fallback routes: core guide and API reference.