Search code examples
javascriptreactjsdomcytoscapereact-ref

Facing issue in selecting the div container in cytoscape() in react.js


I am trying to use cytoscape.js in react.js but while passing the reference in cytoscape function I am facing some errors.

var cy = cytoscape({
  container: document.getElementById('cy'),
  boxSelectionEnabled: false,
  autounselectify: true,

  style: cytoscape.stylesheet()
    .selector('node')
      .style({
        'content': 'data(id)'
      })
    .selector('edge')
      .style({
        'curve-style': 'bezier',
        'target-arrow-shape': 'triangle',
        'width': 4,
        'line-color': '#ddd',
        'target-arrow-color': '#ddd'
      })
    .selector('.highlighted')
      .style({
        'background-color': '#61bffc',
        'line-color': '#61bffc',
        'target-arrow-color': '#61bffc',
        'transition-property': 'background-color, line-color, target-arrow-color',
        'transition-duration': '0.5s'
      }),

  elements: {
      nodes: [
        { data: { id: 'a' } },
        { data: { id: 'b' } },
        { data: { id: 'c' } },
        { data: { id: 'd' } },
        { data: { id: 'e' } }
      ],

      edges: [
        { data: { id: 'ae', weight: 1, source: 'a', target: 'e' } },
        { data: { id: 'ab', weight: 3, source: 'a', target: 'b' } },
        { data: { id: 'be', weight: 4, source: 'b', target: 'e' } },
        { data: { id: 'bc', weight: 5, source: 'b', target: 'c' } },
        { data: { id: 'ce', weight: 6, source: 'c', target: 'e' } },
        { data: { id: 'cd', weight: 2, source: 'c', target: 'd' } },
        { data: { id: 'de', weight: 7, source: 'd', target: 'e' } }
      ]
    },

  layout: {
    name: 'breadthfirst',
    directed: true,
    roots: '#a',
    padding: 10
  }
});

It's showing error while compiling

TypeError: Cannot read properties of null (reading 'className')
Renderer.push../node_modules/cytoscape/dist/cytoscape.cjs.js.BRp$f.init

  26869 | var className = '__________cytoscape_container';
  26870 | var stylesheetAlreadyExists = document.getElementById(stylesheetId) != null;
  26871 | 
> 26872 | if (ctr.className.indexOf(className) < 0) {
        | ^  26873 |   ctr.className = (ctr.className || '') + ' ' + className;
  26874 | }

Is there is any way to solve this problem?

I also tried using Refs to solve this problem instead of using document.getElementById() but getting the same error.


Solution

  • There was such a mistake. I used React hooks: useEffect and useRef. Everything works if you initiate cytoscape after rendering the page.

    import React, { useEffect, useRef } from 'react';
    import { makeStyles } from '@material-ui/core/styles';
    import cytoscape from "cytoscape";
    
    const useStyles = makeStyles(theme => ({
        graph: {
            height: 787,
            width: '100%',
            maxHeight: 787,
        }
    }));
    
    const Graph = props => {
        const classes = useStyles();
        const graph = useRef(null);
        const cy = useRef(null);
    
        useEffect(() => {
            if (graph.current) {   
                cy.current = cytoscape({
                    container: graph.current, 
                    elements: {
                        nodes: [
                          { data: { id: 'a' } },
                          { data: { id: 'b' } },
                          { data: { id: 'c' } },
                          { data: { id: 'd' } },
                          { data: { id: 'e' } }
                        ],
                  
                        edges: [
                          { data: { id: 'ae', weight: 1, source: 'a', target: 'e' } },
                          { data: { id: 'ab', weight: 3, source: 'a', target: 'b' } },
                          { data: { id: 'be', weight: 4, source: 'b', target: 'e' } },
                          { data: { id: 'bc', weight: 5, source: 'b', target: 'c' } },
                          { data: { id: 'ce', weight: 6, source: 'c', target: 'e' } },
                          { data: { id: 'cd', weight: 2, source: 'c', target: 'd' } },
                          { data: { id: 'de', weight: 7, source: 'd', target: 'e' } }
                        ]
                      },
    
                    ready: function () {
                        window.cy = this;
                    }
                });
            }
        }, []);
    
        return (
            <div 
                className={classes.graph}
                ref={graph}
            >
            </div>
        );
    };
     
    export default Graph;