sim51 / react-sigma

Sigma React component
https://sim51.github.io/react-sigma/
Other
158 stars 27 forks source link

ReferenceError: WebGL2RenderingContext is not defined #66

Closed riazXrazor closed 1 month ago

riazXrazor commented 2 months ago

code in page

"use client";

import "@react-sigma/core/lib/react-sigma.min.css";

import React, { useEffect, useState } from "react";
import {
    SigmaContainer,
    useLoadGraph,
    useRegisterEvents,
    useSetSettings,
    useSigma,
} from "@react-sigma/core";

import type { Attributes } from "graphology-types";
import type { FC } from "react";
import { MultiDirectedGraph } from "graphology";
import { animateNodes } from "sigma/utils";
import { useLayoutCircular } from "@react-sigma/layout-circular";

// import EdgeCurveProgram from "@sigma/edge-curve";

function randomNumber(min: number, max: number) {
    return Math.random() * (max - min) + min;
}
const OFFSET = 0;
const sigmaStyle = {
    height: window.innerHeight - OFFSET,
    width: window.innerWidth - OFFSET,
};

const GraphEvents: FC<{ disableHoverEffect?: boolean }> = ({
    disableHoverEffect,
}) => {
    const registerEvents = useRegisterEvents();
    const sigma = useSigma();
    const setSettings = useSetSettings();
    const [draggedNode, setDraggedNode] = useState<string | null>(null);

    const [hoveredNode, setHoveredNode] = useState<string | null>(null);

    useEffect(() => {
        // Register the events
        registerEvents({
            enterNode: (event) => setHoveredNode(event.node),
            leaveNode: () => setHoveredNode(null),
            downNode: (e) => {
                setDraggedNode(e.node);
                sigma.getGraph().setNodeAttribute(e.node, "highlighted", true);
            },
            // On mouse move, if the drag mode is enabled, we change the position of the draggedNode
            mousemovebody: (e) => {
                if (!draggedNode) return;
                // Get new position of node
                const pos = sigma.viewportToGraph(e);
                sigma.getGraph().setNodeAttribute(draggedNode, "x", pos.x);
                sigma.getGraph().setNodeAttribute(draggedNode, "y", pos.y);

                // Prevent sigma to move camera:
                e.preventSigmaDefault();
                e.original.preventDefault();
                e.original.stopPropagation();
            },
            // On mouse up, we reset the autoscale and the dragging mode
            mouseup: () => {
                if (draggedNode) {
                    setDraggedNode(null);
                    sigma.getGraph().removeNodeAttribute(draggedNode, "highlighted");
                }
            },
            // Disable the autoscale at the first down interaction
            mousedown: (e) => {
                const pos = sigma.viewportToGraph(e);
                console.log(pos);
                if (!sigma.getCustomBBox()) sigma.setCustomBBox(sigma.getBBox());
            },
        });
    }, [registerEvents, sigma, draggedNode]);

    useEffect(() => {
        setSettings({
            nodeReducer: (node, data) => {
                const graph = sigma.getGraph();
                const newData = {
                    ...data,
                    highlighted: data.highlighted || false,
                } as Attributes;

                if (!disableHoverEffect && hoveredNode) {
                    if (
                        node === hoveredNode ||
                        graph.neighbors(hoveredNode).includes(node)
                    ) {
                        newData.highlighted = true;
                    } else {
                        newData.highlighted = false;
                    }
                }
                return newData;
            },
            edgeReducer: (edge, data) => {
                const graph = sigma.getGraph();

                const newData = { ...data, hidden: false } as Attributes;

                if (
                    !disableHoverEffect &&
                    hoveredNode &&
                    !graph.extremities(edge).includes(hoveredNode)
                ) {
                    newData.hidden = true;
                }
                if (hoveredNode && graph.extremities(edge).includes(hoveredNode)) {
                    // const node = graph.getNodeAttributes(hoveredNode);
                    newData.size = 5;
                    // newData.color = node.color;
                }

                return newData;
            },
        });
    }, [hoveredNode, setSettings, sigma, disableHoverEffect]);

    return null;
};

const LoadGraph = () => {
    const loadGraph = useLoadGraph();
    const { positions, assign } = useLayoutCircular();
    const sigma = useSigma();

    useEffect(() => {
        const graph = new MultiDirectedGraph();
        graph.addNode("A", {
            x: randomNumber(0, 10),
            y: randomNumber(0, 10),
            label: "Zaman,2020",
            size: 15,
            color: "#6868ff",
            // type: "curvedArrow",
            edgeColor: "red",
        });
        graph.addNode("B", {
            x: randomNumber(0, 10),
            y: randomNumber(0, 10),
            label: "Raffel,2017",
            size: 18,
            color: "#cfcfff",
        });
        graph.addNode("C", {
            x: randomNumber(0, 10),
            y: randomNumber(0, 10),
            label: "Banu,2023",
            size: 12,
            color: "#000",
        });
        graph.addNode("D", {
            x: randomNumber(0, 10),
            y: randomNumber(0, 10),
            label: "Richard,2018",
            size: 18,
            color: "#9494ff",
        });
        graph.addNode("E", {
            x: randomNumber(0, 10),
            y: randomNumber(0, 10),
            label: "Kumar,2020",
            size: 15,
            color: "#6868ff",
        });
        graph.addNode("F", {
            x: randomNumber(0, 10),
            y: randomNumber(0, 10),
            label: "Ghosh,2020",
            size: 20,
            color: "#6868ff",
        });
        graph.addNode("G", {
            x: randomNumber(0, 10),
            y: randomNumber(0, 10),
            label: "Tanwar,2021",
            size: 15,
            color: "#0000ff",
        });
        graph.addNode("AAA", {
            x: randomNumber(0, 10),
            y: randomNumber(0, 10),
            label: "J.Hilley 2021",
            size: 50,
            color: "#0000ff",
        });
        graph.addEdgeWithKey("rel1", "AAA", "A", {
            label: "REL_1",
        });
        graph.addEdgeWithKey("rel2", "AAA", "B", { label: "REL_2" });
        graph.addEdgeWithKey("rel3", "AAA", "C", { label: "REL_3" });
        graph.addEdgeWithKey("rel4", "AAA", "E", { label: "REL_4" });
        graph.addEdgeWithKey("rel5", "AAA", "F", { label: "REL_5" });
        graph.addEdgeWithKey("rel6", "AAA", "G", { label: "REL_6" });
        graph.addEdgeWithKey("rel7", "D", "E", { label: "REL_7" });
        graph.addEdgeWithKey("rel8", "B", "C", { label: "REL_8" });

        graph.addEdgeWithKey("rel9", "A", "AAA", { label: "REL_9" });

        loadGraph(graph);
        // assign();
        animateNodes(sigma.getGraph(), positions(), { duration: 1000 });
    }, [loadGraph, positions, sigma]);

    return null;
};

export default function NetworkGraph() {
    return (
        <SigmaContainer
            // settings={{
            //  defaultEdgeType: "curve",
            //  edgeProgramClasses: {
            //      curve: EdgeCurveProgram,
            //  },
            // }}
            graph={MultiDirectedGraph}
            style={sigmaStyle}
        >
            <LoadGraph />
            <GraphEvents />
        </SigmaContainer>
    );
}

Error on console

ReferenceError: WebGL2RenderingContext is not defined
    at __webpack_require__ (G:\Projects\eurekai-shadcn\.next\server\webpack-runtime.js:33:42)
    at __webpack_require__ (G:\Projects\eurekai-shadcn\.next\server\webpack-runtime.js:33:42)
    at __webpack_require__ (G:\Projects\eurekai-shadcn\.next\server\webpack-runtime.js:33:42)
    at eval (./src/components/network-graph.tsx:10:75)
    at (ssr)/./src/components/network-graph.tsx (G:\Projects\eurekai-shadcn\.next\server\app\graph-prototype\page.js:184:1)
    at __webpack_require__ (G:\Projects\eurekai-shadcn\.next\server\webpack-runtime.js:33:42)
    at eval (./src/app/graph-prototype/page.tsx:9:83)
    at (ssr)/./src/app/graph-prototype/page.tsx (G:\Projects\eurekai-shadcn\.next\server\app\graph-prototype\page.js:173:1)
    at Object.__webpack_require__ [as require] (G:\Projects\eurekai-shadcn\.next\server\webpack-runtime.js:33:42)
    at JSON.parse (<anonymous>)
digest: "3220820615"

lib versions

"@react-sigma/core": "^4.0.2",
"@react-sigma/layout-circular": "^4.0.2",
"@sigma/edge-curve": "^3.0.0-beta.7",
"graphology": "^0.25.4",
"graphology-types": "^0.24.7",
"sigma": "^3.0.0-beta.18",

react and NextJS version

 "next": "14.2.1",
  "next-themes": "^0.3.0",
  "react": "^18",
  "react-dom": "^18",
traitran44 commented 1 month ago

Encountering same issue with nextjs

riazXrazor commented 1 month ago

anyone know what's the cause of this issue ?

sim51 commented 1 month ago

sigma.js must be run into the browser, it used the browser's API to draw the graph (ie. the webgl API). If you render a graph on the server side, those API are not available, that's why you have WebGL2RenderingContext is not defined.

In the FAQ section of the website, there is a tips to use react-sigma with nextjs : https://sim51.github.io/react-sigma/docs/faq#is-it-possible-to-use-this-project-with-nextjs- Can you try it and tell me if it works (it has been written a long time ago, but I think it's still valid) ?

riazXrazor commented 1 month ago

@sim51 thanks , i managed to fix the issue by coding like this

"use client";

import dynamic from "next/dynamic";

const NetworkGraph = dynamic(() => import("@/components/network-graph"), {
    ssr: false,
});

export default function Test() {
    return <NetworkGraph />;
}