Load a graph
Graph property on SigmaContainer
Component SigmaContainer
can take a graph
property which is either a graph instance or a graph constructor.
So you can use it to load your graph.
Loading a graph via the graph property
import { FC, CSSProperties } from "react";
import { MultiDirectedGraph } from "graphology";
import { SigmaContainer } from "@react-sigma/core";
import "@react-sigma/core/lib/react-sigma.min.css";
export const LoadGraphWithProp: FC<{ style: CSSProperties }> = ({ style }) => {
// Create the graph
const graph = new MultiDirectedGraph();
graph.addNode("A", { x: 0, y: 0, label: "Node A", size: 10 });
graph.addNode("B", { x: 1, y: 1, label: "Node B", size: 10 });
graph.addEdgeWithKey("rel1", "A", "B", { label: "REL_1" });
return <SigmaContainer style={style} graph={graph} settings={{ allowInvalidContainer: true }}></SigmaContainer>;
};
By using useLoadGraph
In a children component of SigmaContainer
, you can use the hook useLoadGraph
.
This hook is just returns a function that takes a graphology instance, and load it in Sigma.
Loading a graph with useLoadGraph hook
import { FC, useEffect, CSSProperties } from "react";
import { MultiDirectedGraph } from "graphology";
import { SigmaContainer, useLoadGraph } from "@react-sigma/core";
import "@react-sigma/core/lib/react-sigma.min.css";
const MyGraph: FC = () => {
const loadGraph = useLoadGraph();
useEffect(() => {
// Create the graph
const graph = new MultiDirectedGraph();
graph.addNode("A", { x: 0, y: 0, label: "Node A", size: 10 });
graph.addNode("B", { x: 1, y: 1, label: "Node B", size: 10 });
graph.addEdgeWithKey("rel1", "A", "B", { label: "REL_1" });
loadGraph(graph);
}, [loadGraph]);
return null;
};
export const LoadGraphWithHook: FC<{ style?: CSSProperties }> = ({ style }) => {
return (
<SigmaContainer style={style}>
<MyGraph />
</SigmaContainer>
);
};
Per default, when the SigmaContainer
is mounted, the library create a default graphology graph (see https://graphology.github.io/instantiation.html).
But you can define the type of graph that react-sigma will create by passing the constructor you want to use.
This step is mandatory if you want to use a multi graph (ie. parallel edges).
Defining the graph constructor
import { FC, useEffect, useMemo, CSSProperties } from "react";
import { MultiDirectedGraph as MultiGraphConstructor } from "graphology";
import EdgeCurveProgram, { DEFAULT_EDGE_CURVATURE, indexParallelEdgesIndex } from "@sigma/edge-curve";
import { EdgeArrowProgram } from "sigma/rendering";
import { SigmaContainer, useLoadGraph } from "@react-sigma/core";
import "@react-sigma/core/lib/react-sigma.min.css";
import { useRandom } from "./common/useRandom";
interface NodeType {
x: number;
y: number;
label: string;
size: number;
color: string;
}
interface EdgeType {
type?: string;
label?: string;
size?: number;
curvature?: number;
parallelIndex?: number;
parallelMaxIndex?: number;
}
const MyGraph: React.FC = () => {
const { faker, randomColor } = useRandom();
const loadGraph = useLoadGraph<NodeType, EdgeType>();
useEffect(() => {
// Create the graph
const graph = new MultiGraphConstructor<NodeType, EdgeType>();
graph.addNode("a", {
x: 0,
y: 0,
size: faker.number.int({ min: 4, max: 20 }),
color: randomColor(),
label: faker.person.fullName(),
});
graph.addNode("b", {
x: 1,
y: -1,
size: faker.number.int({ min: 4, max: 20 }),
color: randomColor(),
label: faker.person.fullName(),
});
graph.addNode("c", {
x: 3,
y: -2,
size: faker.number.int({ min: 4, max: 20 }),
color: randomColor(),
label: faker.person.fullName(),
});
graph.addNode("d", {
x: 1,
y: -3,
size: faker.number.int({ min: 4, max: 20 }),
color: randomColor(),
label: faker.person.fullName(),
});
graph.addNode("e", {
x: 3,
y: -4,
size: faker.number.int({ min: 4, max: 20 }),
color: randomColor(),
label: faker.person.fullName(),
});
graph.addNode("f", {
x: 4,
y: -5,
size: faker.number.int({ min: 4, max: 20 }),
color: randomColor(),
label: faker.person.fullName(),
});
graph.addEdge("a", "b", { label: faker.date.anytime().toISOString(), size: faker.number.int({ min: 1, max: 5 }) });
graph.addEdge("b", "c", { label: faker.date.anytime().toISOString(), size: faker.number.int({ min: 1, max: 5 }) });
graph.addEdge("b", "d", { label: faker.date.anytime().toISOString(), size: faker.number.int({ min: 1, max: 5 }) });
graph.addEdge("c", "b", { label: faker.date.anytime().toISOString(), size: faker.number.int({ min: 1, max: 5 }) });
graph.addEdge("c", "e", { label: faker.date.anytime().toISOString(), size: faker.number.int({ min: 1, max: 5 }) });
graph.addEdge("d", "c", { label: faker.date.anytime().toISOString(), size: faker.number.int({ min: 1, max: 5 }) });
graph.addEdge("d", "e", { label: faker.date.anytime().toISOString(), size: faker.number.int({ min: 1, max: 5 }) });
graph.addEdge("d", "e", { label: faker.date.anytime().toISOString(), size: faker.number.int({ min: 1, max: 5 }) });
graph.addEdge("d", "e", { label: faker.date.anytime().toISOString(), size: faker.number.int({ min: 1, max: 5 }) });
graph.addEdge("d", "e", { label: faker.date.anytime().toISOString(), size: faker.number.int({ min: 1, max: 5 }) });
graph.addEdge("e", "d", { label: faker.date.anytime().toISOString(), size: faker.number.int({ min: 1, max: 5 }) });
graph.addEdge("e", "f", { label: faker.date.anytime().toISOString(), size: faker.number.int({ min: 1, max: 5 }) });
graph.addEdge("f", "e", { label: faker.date.anytime().toISOString(), size: faker.number.int({ min: 1, max: 5 }) });
graph.addEdge("f", "e", { label: faker.date.anytime().toISOString(), size: faker.number.int({ min: 1, max: 5 }) });
// Use dedicated helper to identify parallel edges:
indexParallelEdgesIndex(graph, { edgeIndexAttribute: "parallelIndex", edgeMaxIndexAttribute: "parallelMaxIndex" });
// Adapt types and curvature of parallel edges for rendering:
graph.forEachEdge((edge, { parallelIndex, parallelMaxIndex }) => {
if (typeof parallelIndex === "number") {
graph.mergeEdgeAttributes(edge, {
type: "curved",
curvature: DEFAULT_EDGE_CURVATURE + (3 * DEFAULT_EDGE_CURVATURE * parallelIndex) / (parallelMaxIndex || 1),
});
} else {
graph.setEdgeAttribute(edge, "type", "straight");
}
});
// load the graph in sigma
loadGraph(graph);
}, [loadGraph, faker, randomColor]);
return null;
};
export const MultiDirectedGraph: FC<{ style?: CSSProperties }> = ({ style }) => {
// Sigma settings
const settings = useMemo(
() => ({
allowInvalidContainer: true,
renderEdgeLabels: true,
defaultEdgeType: "straight",
edgeProgramClasses: {
straight: EdgeArrowProgram,
curved: EdgeCurveProgram,
},
}),
[],
);
return (
<SigmaContainer style={style} graph={MultiGraphConstructor<NodeType, EdgeType>} settings={settings}>
<MyGraph />
</SigmaContainer>
);
};