Adding new nodes after removing others doesn't work

I’m using react and gojs and I implemented a GraphLinksModel that fits perfectly my needs.
I’m using the contextMenu and after clicking on a button, if this is the root, I clear all the children then I add new ones.
This is the relative code:

//function for clearing nodes and links
removeNodesAndLinks = nodeId => {
    const nodes = myDiagram.model.nodeDataArray    
    if (nodeId === 1 && nodes.length > 1) {
      nodes.filter(node => node.NodeId !== 1).forEach(n => {
        // remove links by selection
        const node = myDiagram.findNodeForKey(n.key)
        myDiagram.selectCollection(node.findLinksConnected())
        myDiagram.commandHandler.deleteSelection()
        //remove nodes
        myDiagram.model.removeNodeData(n)
      })
    }
  }

//this is the addChild function
const addChild = newnode => {
  const selnode = myDiagram.selection.first()
  if (!(selnode instanceof go.Node)) return
  myDiagram.startTransaction("add node and link")
  myDiagram.model.addNodeData(newnode)
  const newlink = { from: selnode.data.key, to: newnode.NodeId }
  myDiagram.model.addLinkData(newlink)
  myDiagram.commitTransaction("add node and link")
}

//this is the add new nodes function
const addNodes = data => {
  data.forEach(node => {
    addChild(node)
  })
}

PROBLEM
If I run addNodes or removeNodesAndLinks one by one, they work perfectly, but if I run the remove and subsequently the add Nodes as I do in the button action it works only the removing phase and not the adding phase.

This is the code in which I create the button and add the action:

this.makeButton(
      "NameA",
      (e, obj) => {
        const contextmenu = obj.part
        const nodedata = contextmenu.data
        this.removeNodesAndLinks(nodedata.NodeId)
        this.fetchTheData("NameA") //after the fetch it run addNodes
      },
     // visiblePredicate
    )

Maybe the problem is that this piece of code, must implement the fetch data function as a callback or as an async/await function?

const node = myDiagram.findNodeForKey(n.key)
myDiagram.selectCollection(node.findLinksConnected())
myDiagram.commandHandler.deleteSelection()
myDiagram.model.removeNodeData(n)

Thanks

Your removeNodesAndLinks function seems very inefficient because it is doing repeated transactions due to your calls to a command (the CommandHandler.deleteSelection method). Not to mention that that command will remove the node from the model data for you already, so your call to Model.removeNodeData should be a no-op.

If you are going to remove everything from the model except for one node, I would think it would be easier to replace the Diagram.model with a new model whose only Model.nodeDataArray contents is the one node data object that you wanted to keep. Something like:

  const arr = [];
  const rootdata = myDiagram.model.findNodeDataForKey(nodeId);
  if (rootdata) arr.push(rootdata);
  myDiagram.model = new go.GraphLinksModel(arr);

Your addNodes function suffers from the same problem of performing repeated transactions rather than just a single transaction that surrounds the whole loop. (But nested transactions are OK, in case you want to call addChild independently.)

Dear Walter,
due to your help my code became faster.
I replaced the model leaving only the root node in the removeNodesAndData and then in the addNodes function I used addNodeDataCollection and addLinkDataCollection like this:

const addNodes = (data, links) => {
  myDiagram.model.addNodeDataCollection(data)
  myDiagram.model.addLinkDataCollection(links)
}

Right now the code works very well but I lost the beautiful animation effect that I had using this code:

const addChild = newnode => {
  const selnode = myDiagram.selection.first()
  if (!(selnode instanceof go.Node)) return
  myDiagram.startTransaction("add node and link")
  myDiagram.model.addNodeData(newnode)
  const newlink = { from: selnode.data.key, to: newnode.NodeId }
  myDiagram.model.addLinkData(newlink)
  myDiagram.commitTransaction("add node and link")
}

const addNodes = (data) => {  
  data.forEach(node => {
     addChild(node)
  })
}

Is it possible to have an animation using the addNodeDataCollection and addLinkDataCollection functions?
Thanks

It may depend on when you call addNodes. Try this:

function addNodes(data, links) {
  myDiagram.model.commit(m => {
    m.addNodeDataCollection(data);
    m.addLinkDataCollection(links);
  }, "added nodes and links");
}

Does this do what you want?

I was using this solution:

  data.forEach(node => {
    myDiagram.startTransaction("add node")
    myDiagram.model.addNodeData(node)
    myDiagram.commitTransaction("add node")
  })

  links.forEach(link => {
    myDiagram.startTransaction("add link")
    myDiagram.model.addLinkData(link)
    myDiagram.commitTransaction("add link")
  })

but your as always is better! :D
Thanks