Dynamically creating nodes from JSON does not work after initial save

804 Views Asked by At

I am new to react, trying to dynamically create nodes using ReactFlow based off of a JSON. Using the code below, I will save my index.tsx and push a button which calls onAdd function, and it will work (creates the expected nodes). However, once I refresh the browser, the button stops working.

function Flow() {
  const [nodes, setNodes, onNodesChange] = useNodesState(initialNodes);
  const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges);
  const [newNodes, setNewNodes] = useState([])

  const handleClick = () => {
    fetch('/get_nodes')
    .then((r) => r.json())
    .then(data  => {
      console.log(data)
      setNewNodes(data)
    })
    
  } 
  
  const onAdd = useCallback(() => {
    handleClick()

    console.log(newNodes)


    setNodes((nds) => nds.concat(newNodes));
  }, [setNodes]);

I have not tried too much, I have been trying to google this problem for a bit and I don't know how to describe my issue other than listed above. This is likely more related to React than ReactFlow specific.

1

There are 1 best solutions below

2
On

Many React errors described as "component X works only one time" are related to React's dependencies arrays.

These are arrays passed into hooks, usually as a second parameter, which tells the hook it should not rerender unless one of the array's elements have changed (usually this technique is used for performance's sake, avoiding to redo expensive computing if its inputs are the same). This array is present in many hooks, such asuseEffect, useCallback (https://reactjs.org/docs/hooks-reference.html#usecallback), useMemo.

In your code, onAdd should be called whenever nodes changed, but you passed setNodes as the dependency. Considering setNodes refers to the setter function, not to the nodes themselves, and considering the setter function doesn't change when it adds a node, the onAdd is called only the first time, and never after.

To address the issue, it's just explain to your useCallback it depends on the nodes, not on its setter function:

const onAdd = useCallback(() => {
    //Inner logic
}, [nodes]); // changed here