GoJS with React. store data in the state

Hi, I would like to store the model of my diagram to the state of my component and then maybe later to the store
Here is my code :

    myDiagram.addDiagramListener("ExternalObjectsDropped", function(){
      this.saveJson(myDiagram.model.toJson());
      console.log("network : ", myDiagram.model.toJson());
    });

this is called in the renderCanvas method which is called in ComponentDidMount
The console.log works fine but the function saveJson is undefined

Any idea why the “this” is concidered undefinied ?
thanks

this in that context is not well defined and you shouldn’t be using it. You are not defining something on the Diagram’s prototype so this is just whatever it was in the outside scope, or potentially nothing.

You could try making a closure:

var self = this; // if you are sure of what 'this' is here
myDiagram.addDiagramListener("ExternalObjectsDropped", function(){
  self.saveJson(myDiagram.model.toJson());
  console.log("network : ", myDiagram.model.toJson());
});

But the method saveJson() is defined in the component in the same level as the constructor of the component.

componentDidMount() {
    this.renderCanvas();
  }

  saveJson(model){
    this.setState({networkModel: model}, ()=>{
      console.log("Network : ", this.state.networkModel);
    });
  }

render(){
...
}

knowing that the listener is called inside the renderCanvas()

Also I have binded the method in the constructor of the component :

constructor(){
this.saveJson = this.saveJson.bind(this);
}

I have found a solution if someone got the same problem.
For some reason this is undefined in a GoJs eventListener. so in the beggining of my renderCanvas

let selfComp = this;

then in my listener :

myDiagram.addDiagramListener("ExternalObjectsDropped", function(){
  selfComp.saveJson(myDiagram.model.toJson());
});

It works just fine.
Thank you Simon for your help !

It might be easier to replace the use of function() { ... } with () => { ... }. That’s JavaScript for you.

No GoJS event listeners or functional properties ever have this bound when called. That’s because when we designed the API we knew that some day there would be “arrow functions”. Although at the time I don’t think we even knew about the syntax or that they would be called “arrow functions”. It’s been too long for me to remember…

The only functions that have this bound are methods of classes, some of which may be overridden.

We are using GoJS with React and like Walter said arrow functions solve the problem of this.

  onChangedSelection = e => {
    const { onChangedSelection } = this.props;
    let node;
    const nodes = [];
    let link;
    const links = [];

    const iter = e.diagram.selection.iterator;
    while (iter.next()) {
      if (iter.value instanceof go.Node) {
        node = iter.value;
        if (node.data) {
          nodes.push(node.data.id);
        }
      } else if (iter.value instanceof go.Link) {
        link = iter.value;
        if (link.data) {
          links.push(link.data.id);
        }
      }
    }

    onChangedSelection(nodes, links);
  };

  renderCanvas = () => {
    ...
    this.diagram.addDiagramListener('ChangedSelection', this.onChangedSelection);
    this.diagram.addModelChangedListener(event => onModelChanged(event, this.diagram));

  }