4

I am using React with dhtmlx-gantt library to create gantt chart. I met with issue when using the filter function together with useEffect/useLayoutEffect lifecycle.

The gist of it is that the browser is not painting/rendering the correct UI on the screen on certain condition.

The start state load screen looks like this:
6 Task

on-load

After filter, this should be how it looks like:
Should be left with 5 task after filtering away duration > 4

on-correct-filter

But this is how it is:
Left with 5 task but an empty row is shown rather than "refreshing" (not sure if this is the right term to use)

on-wrong-filter

I have created a github repo with different scenario describing the problem, and how to reproduce those issue. More information on how to run the sample can be found in the README.md. Please let me know if more information needs to be provided.

Sample 1: Using conditional rendering will cause issue on painting UI changes
Sample 2: Turning smart_rendering config on and off cause issue on painting UI changes
Sample 3: Calling the function within the parent component and in child component with exact same code cause issue on painting UI

My desired outcome is to able to render the UI correctly, whether or not this code to filter the data is ran on parent or child component.

I should also mention that a workaround was to use if (document.querySelector(".gantt_grid")) gantt.render(); rather than gantt.refreshData() in onBeforeTaskDisplay event which will then correctly paint the UI changes. But I still like to understand why does this happens. Is there anything I did wrongly in term of using the React lifecycle and so on.

Thank you.

user1778855
  • 427
  • 8
  • 25

2 Answers2

0

Try gantt.render() after gantt.refreshData() in your code:

    useEffect(() => {
        const onBeforeTaskDisplay = gantt.attachEvent("onBeforeTaskDisplay", function (id, task) {
            console.log("filters", task.text, filter)
            if (filter && task.duration > 4) {
                return false;
            }
            return true;
        });
        gantt.refreshData();
        gantt.render();

        // This should have been here
        return () => {
            gantt.detachEvent(onBeforeTaskDisplay);
        }
    }, [filter])
Sergey Kirienko
  • 219
  • 3
  • 9
0

Your code looks fine and should work correctly.

The issue is on dhtmlxGantt end, it has been confirmed and is now fixed in the dev branch.

The bug itself was caused by the new smart rendering mechanism introduced in v6.2.0. It caches previously calculated positions of tasks in order to minimize calculations. In certain circumstances when a gantt instance has been initialized multiple times, it didn't invalidate that cache when it was necessary. Because of that, tasks were displayed at the same positions as they had before filtering was applied (thus the blank row where the first task has been).

In short, the issue will be fixed in the next bugfix update - v6.2.6.

If everything goes as planned, it will be released tomorrow (2019-09-19)

Alex Klimenkov
  • 876
  • 1
  • 5
  • 8