Create React Gantt Chart Component with dhtmlxGantt

We won’t stop till show you that you can use our Gantt chart library with any technology! And today is the turn of ReactJS, popular JavaScript component-based library. Following the steps of this tutorial, you’ll know how to create React Gantt chart app with some basic features. So, let’s start.

What we have done here – we’ve initialized dhx gantt once the component is mounted to DOM and populated it with the data from props.

A `gantt` variable we use here is defined globally in the dhtmlx-gantt module and not in the app code, so the compiler knows nothing about it. If we leave it as is, the default ESLint settings will give you a ‘gantt is undefined’ error when you try to compile the app.

In order to prevent it, we’ll declare it using a special comment that will tell the linter that everything is under control:

Note, that since dhtmlxGantt has no destructor, we do not define componentWillUnmount. That also means that if we remove a component from react at some point, the instance of dhtmlxGantt will stay in memory and will be reused next time when the component is mounted again.

Now let’s add gantt to our App component. Note that we use hard-coded data for this sample:

Pay your attention to a couple of important things here. When using dhtmlxGantt, it’s expected that the chart will be mounted to DOM using gantt.init, and all further repaints will be called using gantt.render.

Now, each time user selects zoom level in a toolbar, changes will be captured by App which will then pass an updated state to Gantt.

Processing Changes Made in Gantt

What else would you need while adding gantt chart to your app? Most probably you’ll need to do something with changes that users make in gantt chart – send changes to the backend or update other components.

In this tutorial we won’t cover saving changes to the db, instead, we’ll show how to capture these changes, and then pass them somewhere in the app.

In order to do so, we’ll capture the related API events of dhtmlxGantt, send them to the parent component, and then show the list of changes somewhere on the page.

Open Gantt.js and add the following code right before gantt initialization:

How everything works now – each time user changes something in gantt, we capture that action in the App component and update MessageArea which prints action details on a page. It’s exactly what we wanted.

If we run the app now and change some tasks or links, we should see appropriate messages under the gantt chart.

We’ve just found out that the error may happen if you skip /*global gantt*/ declaration from Gantt.js code. Since Gantt instance is declared in dhtmlxgantt module and we access it via a global variable, we add a declaration-comment to make eslint: https://eslint.org/docs/rules/no-undef know about it and not throw ‘not defined’ error. We’ve updated the tutorial to avoid this problem.

FedeNovember 21, 2017 at 5:06 pm

I was able to implement the component in React (with Meteor, React Router) and it was great. However, I have a big problem: every time I leave the gantt and to go to another module and then return, the events of the tasks (add, modify, delete, etc) are doubled or tripled. Any ideas?

Hi Fede,
Event listeners that are attached on componentDidMount do not disappear when the component is unmounted, so you get a new set of listeners each time you re-mount the component.
The simplest workaround is to set some flag in order to apply events only once:
componentDidMount() {

But… if i use a React Property i can’t change the it’s value. If i use a state, it doen’t work becouse it is overwritten. If i use a js variable like
constructor(props){ this.flag = false } i have the same problem.
This “gantt.$eventsAttached” is a flag that i should create in some js over the react files? Maybe in a node-modules/dhtmlx-gantt directory?

Hi there,
I was kind of facing the same issue described by Fede. I was able to solve it with the workaround suggested.
Now… I have another big issue, I am not using the lightbox to create new tasks. Instead, I open a modal and let the user insert all the data in a form. After clicking on “save and close”, I am saving my new task in the database using Axios.
After doing that I set a different value to a state variable, so the component should render again, and retrieve data from my database. I was able to do all that, but the component won’t refresh the new data it is receiving.
Do you think you can help me out?