Gantt - Memory Leak when using custom react controls

Hi - I’ve implemented the gantt control in two sections. One instance has no react controls and seems to be working fine while the other I have implemented react onrender functionality as per - Specifying Columns Gantt Docs

The issue is that with this control the memory usage goes absolutely crazy. Even though I’m using pretty standard fluent ui controls for this. I’m on version 7.1.8 and just wondering if this is a known issue or if there is a way to clean up these controls.

Hello Skoofy,
Unfortunately, there is no ready event handler for detaching React components. The only solution is to use various event handlers like onBeforeDataRender and manually detach the components there.
You can check how it is done in the following demo:
https://files.dhtmlx.com/30d/bcac2d270e7cf8f74f9271d74ffc489b/reactive-gantt+gantt-instance+react-components.zip

In the future, the dev team will add that functionality, but I cannot give you any ETA.

Thanks, ramil.

This seems to be the relevant code:

 function detachReactNodes(){
      var nodes1 = document.querySelectorAll(`.gantt_cell[data-column-index="3"]`)
      nodes1.forEach(function (node) {
        ReactDOM.unmountComponentAtNode(node);
      });
      var nodes2 = document.querySelectorAll(`.gantt_cell[data-column-index="4"]`)
      nodes2.forEach(function (node) {
        ReactDOM.unmountComponentAtNode(node);
      });
    }

    function detachSpecificReactNode(id) {
      ReactDOM.unmountComponentAtNode(document.querySelector(`[data-task-id="${id}"] .gantt_cell[data-column-index="3"]`));
      ReactDOM.unmountComponentAtNode(document.querySelector(`[data-task-id="${id}"] .gantt_cell[data-column-index="4"]`));
    }

    gantt.attachEvent("onBeforeDataRender", function () {
      detachReactNodes();
    });

    gantt.attachEvent("onBeforeTaskSelected", function (id, e) {
      detachSpecificReactNode(id);
      return true;
    });
    gantt.attachEvent("onTaskDrag", function (id, mode, task, original) {
      detachSpecificReactNode(id);
    });

    let linkAdd = null;
    gantt.attachEvent("onMouseMove", function (id, e) {
        if (document.querySelector(".gantt_link_direction") && linkAdd === null) {
            detachSpecificReactNode(id);
            linkAdd = "started";
        }
        if (linkAdd && !document.querySelector(".gantt_link_direction")) {
            linkAdd = null;
        }
    });

I think I’ve made the code a little more generic so it will target all columns with a custom render specified:

 function detachReactNodes() {

     const ganttColumns = gantt.getGridColumns();

     for (let i = 0; i < ganttColumns.length; i++) {

         var columnNode = document.querySelectorAll(`.wf > .gantt_cell[data-column-index="${i}"]`)

         if (ganttColumns[i]['onrender'] !== undefined) {
             columnNode.forEach(function (node) {
                 ReactDOM.unmountComponentAtNode(node);
             });
         }

     }
 }

function detachSpecificReactNode(id: any) {


    const ganttColumns = gantt.getGridColumns();

    for (let i = 0; i < ganttColumns.length; i++) {

        let columnIdNode: any = document.querySelector(`.wf[data-task-id="${id}"] > .gantt_cell[data-column-index="${i}"]`);

        if (ganttColumns[i]['onrender'] !== undefined) {

            if (columnIdNode !== null) {
                ReactDOM.unmountComponentAtNode(columnIdNode);
            }
        }

    }
}

However, I’ve noticed that, particularly for dragging tasks, the gantt is not as performant now these being called. It does seem to be managing memory a little better - is there really no alternative to this?

Hello Skoofy,
When you drag a task, Gantt repaints the task row a lot. So, the code to add React components and detach them is also called a lot of times. A better way for performance would be to not attach React components until you finish the task drag.
Right now, there is no way to change how it works as Gantt doesn’t reuse the existing DOM elements and creates new ones. This may work more or less OK with the DOM and HTML elements, but it seems that it takes more time for React to do the same thing.
In the future, the dev team will change how rendering works, but I cannot give you any ETA.

One of the possible alternatives would be to attach React elements to a DOM element beyond Gantt and manually handle how everything works. But I don’t have a ready solution for that.