title: Uncaught TypeError: *** is not a function in a React component
body: <p>I'm passing an object as an argument in a React component's constructor. Then, I want to call one of the object's function, but get this error message:</p>
  
  <pre><code>Uncaught TypeError: _this.layout.getWbsLayout is not a function
      at new Wbs (Wbs.tsx:50)
      at react-dom.js:4749
      at measureLifeCyclePerf (react-dom.js:4529)
      at ReactCompositeComponentWrapper._constructComponentWithoutOwner (react-dom.js:4748)
      at ReactCompositeComponentWrapper._constructComponent (react-dom.js:4734)
      at ReactCompositeComponentWrapper.mountComponent (react-dom.js:4642)
      at Object.mountComponent (react-dom.js:11542)
      at ReactCompositeComponentWrapper.performInitialMount (react-dom.js:4825)
      at ReactCompositeComponentWrapper.mountComponent (react-dom.js:4712)
      at Object.mountComponent (react-dom.js:11542)
  </code></pre>
  
  <p>I read some posts about binding methods to this in the constructor, but as I am calling a function of an object I passed as an argument, I am not sure this applies here, and still got a similar message saying <code>bind is not a function</code>.</p>
  
  <p>Here's my code, <code>Wbs</code> is the root React component, <code>WbsLayout</code> is an object I pass as a parameter to Wbs' constructor.</p>
  
  <p>The error happens in the constructor, when I do <code>this.layout.getWbsLayout()</code>
  Note that I tried to call the function in <code>ComponentDidMount</code> instead, but got the same error.</p>
  
  <pre><code>import * as React from 'react';
  import WbsLayout from "../layout/WbsLayout";
  
  interface WbsProps {}
  interface WbsState {
      wbsElements: any[];
      wbsEdges: any[]
  }
  
  class Wbs extends React.Component&lt;WbsProps, WbsState&gt;{
  
      public cy: Cy.Instance;
      private layout: WbsLayout;
      private s: snap.Paper;
      private renderer: WbsRenderer;
  
      public state : WbsState;
  
      constructor(props: WbsProps, layout: WbsLayout) {
          super(props);
          this.layout = layout;
          this.cy = this.layout.cy;
  
          // this does show a json object in the console, hence layout can be accessed
          console.log(layout.cy.elements().jsons());
  
          this.layout.getWbsLayout(); //The error happens here
  
          // initial state
          this.state = {
              wbsElements: [],
              wbsEdges: [],
          };
      }
  
      public render() {
  
          const wbsElements: any = this.state.wbsElements.map((element: any) =&gt; (
              &lt;WbsElement
                  key={element.wbsElementBox.nodeId}
                  wbsElementBox={...element.wbsElementBox}
                  wbsElementTitle={...element.wbsElementTitle}
                  wbsElementId={...element.wbsElementId}
              /&gt;
          ));
  
          const wbsEdges: any = this.state.wbsEdges.map((edge: any) =&gt; (
              &lt;WbsEdge
                  key={edge.edgeId}
                  edgeId={edge.edgeId}
                  sourceWbsElementData={...edge.sourceWbsElementData}
                  targetWbsElementData={...edge.targetWbsElementData}
              /&gt;
          ));
  
          return (
              &lt;svg&gt;
                  {wbsElements}
                  {wbsEdges}
              &lt;/svg&gt;
          );
      }
  }
  
  export default Wbs;
  </code></pre>
  
  <p>Here's <code>WbsLayout</code>:</p>
  
  <p>export class WbsLayout  {</p>
  
  <pre><code>    public cy: Cy.Instance;
  
      constructor(graph: any, Options?: Options) {
  
          this.cy = cytoscape({
              headless: true,
              elements: graph
          });
  
      }
  
      public getWbsLayout(): any {
          const wbsElements: any = this.cy.collection("node[visibility = 'visible']").map((n: Cy.CollectionNodes) =&gt;
              ({
                  wbsElementBox: {
                      nodeId: n.data().id,
                      x: n.data().x,
                      y: n.data().y,
                      width: n.data().width,
                      height: n.data().height
                  },
                  wbsElementTitle: {
                      text: n.data().title
                  },
                  wbsElementId: {
                      text: n.data().wbsId
                  }
              })
          );
  
          const wbsEdges: any = [
              {
                  edgeId: '5',
                  sourceWbsElementData: {
                      nodeId: '1',
                      x:464.359375,
                      y:30,
                      width:100,
                      height:40,
                      layoutStyle: 0
                  },
                  targetWbsElementData: {
                      nodeId:'1.5',
                      x:867.875,
                      y:100,
                      width:130.84375,
                      height:40,
                      layoutStyle: 1
                  }
  
              }
          ];
  
          return {
              wbsElements,
              wbsEdges
          };
      }
  
      ....
  }
  export default WbsLayout;
  </code></pre>
  
  <p>Here's how I instantiate Wbs:</p>
  
  <pre><code>let graph: any = {
      nodes: [],
      edges: []
  };
  
  let layout: WbsLayout = new WbsLayout(graph);
  let wbs = new Wbs(null, layout);
  </code></pre>
  
  <p>I can see json objects in Wbs' constructor:
      console.log(layout.cy.elements().jsons());</p>