crubier / react-graph-vis

A react component to render nice graphs using vis.js

Home Page:http://crubier.github.io/react-graph-vis/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Cannot Update Graph - Errors Thrown

FA5I opened this issue · comments

commented

Hi,

I am playing around with the library, but one thing that is not clear to me is how I can update the graph?

The below issue only arises if I try to create nodes greater than or equal to 5.

My code is as App.js follows:

import React, { useState } from 'react'
import './App.css'
import Graph from 'react-graph-vis'
import { v4 as uuidv4 } from 'uuid'
import cloneDeep from 'lodash/cloneDeep'

function App() {
  let nodes = [
    { id: 1, label: '1', title: '1' },
    { id: 2, label: '2', title: '2' },
    { id: 3, label: '3', title: '3' },
    { id: 4, label: '4', title: '4' },
    { id: 5, label: '5', title: '5' },
  ]

  let edges = [
    { from: 1, to: 2 },
    { from: 1, to: 3 },
    { from: 2, to: 4 },
    { from: 2, to: 5 },
  ]

  let default_graph = {
    edges: edges,
    nodes: nodes,
  }

  let [graph, setGraph] = useState(default_graph)
  let [user_input, setUserInput] = useState('')

  const options = {
    layout: {
      hierarchical: false,
    },
    edges: {
      color: '#000000',
    },
    height: '500px',
  }

  const events = {
    select: function (event) {
      let { nodes, edges } = event
    },
  }

  function handleChange(event) {
    setUserInput(event.target.value)
  }

  function handleClick(event) {
    let raw_input = user_input

    console.log(raw_input)

    if (raw_input === '') {
      return
    }

    let input = raw_input.split('\n')
    // this tells how us how many nodes to create
    let n = parseInt(input[0])

    let new_graph = {}
    let new_nodes = []
    let new_edges = []

    // create nodes - issue appears to be here
    for (let i = 1; i <= n; i++) {
      let node = {
        id: i,
        label: `${i}`,
        // title: `${i}`,
      }
      new_nodes.push(node)
    }

    new_graph['nodes'] = new_nodes

    setGraph(new_graph)
  }

  return (
    <div>
      <nav>
        <a href=""> back to Homepage</a>
      </nav>
      <div className="button-container">
        <button onClick={handleClick}>Draw Graph</button>
      </div>
      <div className="App">
        <textarea
          id="user-input"
          className="inputs"
          onChange={handleChange}
        ></textarea>
        <div className="graph-container">
          <Graph
            key={uuidv4}
            graph={graph}
            options={options}
            events={events}
            getNetwork={(network) => {}}
          />
        </div>
      </div>
    </div>
  )
}

export default App

This however throws a bunch of errors as follows:

Screenshot 2020-09-16 at 21 05 52

Could someone please explain how I can get the graph to be updated with the new one I constructed in my handleClick function?

I am somewhat new to React, so any advice would be much appreciated.

EDIT:

I had a look at this issue:

https://github.com/crubier/react-graph-vis/issues/83

I added a UUID key for the Graph component too, but that doesn't seem to work

Hello I had the same problem. I was able to fix it by removing the <React.StrictMode> tag from the index.js file.

commented

Hello I had the same problem. I was able to fix it by removing the <React.StrictMode> tag from the index.js file.

Thanks, but do you know any way to fix this without removing <React.StrictMode>? I would like to keep that tag for the rest of the application.

commented

Actually I figured it out.

You need to generate a new key every time you create a new graph.

A simple way is to just add the following to state:

let [graphKey, setGraphKey] = useState(uuidv4)

Once that is generated, pass it as the key prop to your new graph. This new key will ensure that the old component will be unmounted and cleared, and so the new component can be mounted without any trouble.

Nice, thanks.

Any example with useEffect? After receive the API response i need to update my graph. The id problem still occuring in my case.

Any example with useEffect? After receive the API response i need to update my graph. The id problem still occuring in my case.

key={uuidv4()} works for me, basically what OP did originally

I updated my graph with the response from an API using useEffect

I found out where the issue is.

In StrictMode, things like shouldComponentUpdate are called multiple times to simulate how concurrent mode will work. In the shouldComponentUpdate function, this is performing side effects.
Specifically, it's calling patchNodes , patchEdges, Network.setOptions, Network.off in there, rather than causing an update.

https://reactjs.org/docs/strict-mode.html#detecting-unexpected-side-effects

Because the above methods might be called more than once, it’s important that they do not contain side-effects. Ignoring this rule can lead to a variety of problems, including memory leaks and invalid application state. Unfortunately, it can be difficult to detect these problems as they can often be non-deterministic.

Hi, any proposed fix for this issue rather than destroying and mounting again the component? That is not an ideal solution, as it defeats the purpose of react of rendering as few changes as possible. It also prevents nicely animating the node being added. @crubier happy to help implement it if necessary

Hi, any proposed fix for this issue rather than destroying and mounting again the component? That is not an ideal solution, as it defeats the purpose of react of rendering as few changes as possible. It also prevents nicely animating the node being added. @crubier happy to help implement it if necessary

I put up a gist that I put together from re-writing this library as a hook-based component, which solved the above issue (and a few others): https://gist.github.com/ZachHaber/feb0432fe395a303a4f10671877e5e70

I originally put it here, b/c I wasn't sure where it belonged and I assumed that github would say that this issue was referenced, but I guess that didn't happen.
#105 (comment)

Hope this helps!

@ZachHaber you're a life saver. I have been re-writing the library just like you did for a few hours now, but didn't manage to make it to the finish line. Will just use your code now. You should open a PR so we can use the hook-based component instead!

I wasn't sure about opening a PR because A, nothing has seemingly happened in this this repo for a while, and it's pretty much a complete re-write, so I wasn't sure about it.

Perhaps it's worth putting into a new repo? @ZachHaber

Hi there, I was trying the uuid solution mentioned above but unsuccessful.
I am not an expert. Please if someone can help me resolve this issue.

ISSUE: double click anywhere in the canvas and it throws error.
I have put together a codesandbox for quick reference: https://codesandbox.io/s/jio-nodegraph-forked-ssqn30?file=/src/NetworkGraph.js

const version = useMemo(uuidv4, [graph, update, windowWidth]);

is what I used for the key.

I used this library over a year ago so I am not sure exactly what my fix was but looking at my code, I am updating the version (which is used as the key for the graph) whenever any of those variables change. I think you can do something like

const version = useMemo(uuidv4, [graph])

with key = {version} because it seems like the graph is being updated without the key being updated.

Anyway, here is my code: https://github.com/lucy-shen/react-flask-graph/blob/master/react/src/Graph.js

Any example with useEffect? After receive the API response i need to update my graph. The id problem still occuring in my case.

key={uuidv4()} works for me, basically what OP did originally

I updated my graph with the response from an API using useEffect

This worked for me, thank you

This worked for me. Thanks!

import uuid from "react-uuid";

<Graph
        key={uuid()}
        graph={graph}
        options={options}
        events={events}
        style={{ height: "700px" }}
      />