{"id":4066,"date":"2017-05-24T20:00:26","date_gmt":"2017-05-24T16:00:26","guid":{"rendered":"https:\/\/dhtmlx.com\/blog\/?p=4066"},"modified":"2026-01-30T11:50:43","modified_gmt":"2026-01-30T08:50:43","slug":"create-react-gantt-chart-component-dhtmlxgantt","status":"publish","type":"post","link":"https:\/\/dhtmlx.com\/blog\/create-react-gantt-chart-component-dhtmlxgantt\/","title":{"rendered":"Create React Gantt Chart Component with dhtmlxGantt"},"content":{"rendered":"<p><strong>Updated on February 07, 2022<\/strong><\/p>\n<p>We won&#8217;t stop till show you that you can use our <a href=\"\/\/dhtmlx.com\/docs\/products\/dhtmlxGantt\/\" target=\"_blank\">Gantt chart library<\/a> with any technology! And today is the turn of ReactJS, a popular JavaScript component-based library. Following the steps of this tutorial, you&#8217;ll know how to create React Gantt chart app with some basic features. So, let&#8217;s start.<\/p>\n<p><strong>As always, you can find <a href=\"https:\/\/github.com\/DHTMLX\/react-gantt-demo\" target=\"_blank\">React gantt chart component demo on GitHub<\/a>.<\/strong><\/p>\n<h4>Creating a Simple React App<\/h4>\n<p>The very first thing we need to do is to initialize the application structure. For this, we are going to use Create React app tool. It can be installed with the following command:<\/p>\n<div class=\"codecolorer-container javascript default codecolorer-noborder\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\">yarn global add create<span class=\"sy0\">-<\/span>react<span class=\"sy0\">-<\/span>app<\/div><\/div>\n<p>You can find some additional information in <a href=\"https:\/\/react.dev\/learn\" target=\"_blank\">this article<\/a>. <\/p>\n<p>Then we create an app:<\/p>\n<div class=\"codecolorer-container javascript default codecolorer-noborder\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\">npx create<span class=\"sy0\">-<\/span>react<span class=\"sy0\">-<\/span>app gantt<span class=\"sy0\">-<\/span>react<\/div><\/div>\n<p>When our app is created, we go to the folder and run it for the first time:<\/p>\n<div class=\"codecolorer-container javascript default codecolorer-noborder\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\">cd gantt<span class=\"sy0\">-<\/span>react<br \/>\nyarn start<\/div><\/div>\n<p>The first steps are completed, and as a result, our app should be started on <strong>http:\/\/localhost:3000\/<\/strong><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/dhtmlx.com\/blog\/wp-content\/uploads\/2017\/05\/gantt-chart-react-1.png\" alt=\"gantt chart react\" width=\"512\" height=\"250\" class=\"aligncenter size-full wp-image-6189\" srcset=\"https:\/\/dhtmlx.com\/blog\/wp-content\/uploads\/2017\/05\/gantt-chart-react-1.png 512w, https:\/\/dhtmlx.com\/blog\/wp-content\/uploads\/2017\/05\/gantt-chart-react-1-300x146.png 300w\" sizes=\"auto, (max-width: 512px) 100vw, 512px\" \/><\/p>\n<h4>Style agreement<\/h4>\n<p>In this tutorial, we&#8217;ll use the following folder structure:<br \/>\n &#8211; Each component will be placed inside a separate folder, named after the component.<br \/>\n &#8211; Each folder will contain an index.js file, which will explicitly specify which classes are exported by the component, and a file with the component implementation.<br \/>\nFor example, when we create our Gantt component, it will have the following structure:<\/p>\n<div class=\"codecolorer-container javascript default codecolorer-noborder\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\">.<span class=\"sy0\">\/<\/span>src<span class=\"sy0\">\/<\/span>components<span class=\"sy0\">\/<\/span>Gantt<span class=\"sy0\">\/<\/span><br \/>\n<span class=\"sy0\">|-<\/span> Gantt.<span class=\"me1\">js<\/span><br \/>\n<span class=\"sy0\">|-<\/span> index.<span class=\"me1\">js<\/span><br \/>\n<span class=\"sy0\">|-<\/span> Gantt.<span class=\"me1\">css<\/span><\/div><\/div>\n<p>Gantt.js will contain the implementation of the component, and index.js will export it:<\/p>\n<div class=\"codecolorer-container javascript default codecolorer-noborder\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\"><span class=\"kw5\">import<\/span> Gantt from <span class=\"st0\">'.\/Gantt'<\/span><span class=\"sy0\">;<\/span><br \/>\n<span class=\"kw5\">import<\/span> <span class=\"st0\">'.\/Gantt.css'<\/span><span class=\"sy0\">;<\/span><br \/>\n<span class=\"kw5\">export<\/span> <span class=\"kw1\">default<\/span> Gantt<span class=\"sy0\">;<\/span><\/div><\/div>\n<p>And the outer code will import the folder<\/p>\n<div class=\"codecolorer-container javascript default codecolorer-noborder\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\"><span class=\"kw5\">import<\/span> <span class=\"br0\">&#123;<\/span> Gantt <span class=\"br0\">&#125;<\/span> from <span class=\"st0\">&quot;.\/components\/Gantt&quot;<\/span><span class=\"sy0\">;<\/span><\/div><\/div>\n<p>That way if we add extra components to our Gantt, they will be defined under the same folder and it won&#8217;t affect imports and won&#8217;t clutter our folder structure.<br \/>\nNow, when we&#8217;ve sorted it out, we can proceed.<\/p>\n<p>Let us start with our Gantt component.<br \/>\nThe first thing you need is to add dhtmlxGantt package to your project.<br \/>\nA free version of it can be added via npm or yarn:<\/p>\n<div class=\"codecolorer-container javascript default codecolorer-noborder\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\">yarn add dhtmlx<span class=\"sy0\">-<\/span>gantt<\/div><\/div>\n<p>Then, create the <em>src\/components\/Gantt<\/em> folder.<br \/>\nHere we&#8217;ll add a React Component wrapper for dhtmlxGantt.<br \/>\nCreate Gantt.js file and open it:<br \/>\n<em>src\/components\/Gantt\/Gantt.js:<\/em><\/p>\n<div class=\"codecolorer-container javascript default codecolorer-noborder\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\"><span class=\"kw5\">import<\/span> React<span class=\"sy0\">,<\/span> <span class=\"br0\">&#123;<\/span> Component <span class=\"br0\">&#125;<\/span> from <span class=\"st0\">'react'<\/span><span class=\"sy0\">;<\/span><br \/>\n<span class=\"kw5\">import<\/span> <span class=\"br0\">&#123;<\/span> gantt <span class=\"br0\">&#125;<\/span> from <span class=\"st0\">'dhtmlx-gantt'<\/span><span class=\"sy0\">;<\/span><br \/>\n<span class=\"kw5\">import<\/span> <span class=\"st0\">'dhtmlx-gantt\/codebase\/dhtmlxgantt.css'<\/span><span class=\"sy0\">;<\/span><br \/>\n<span class=\"kw5\">import<\/span> <span class=\"st0\">'.\/Gantt.css'<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp;<br \/>\n<span class=\"kw5\">export<\/span> <span class=\"kw1\">default<\/span> <span class=\"kw5\">class<\/span> Gantt <span class=\"kw5\">extends<\/span> Component <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; componentDidMount<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; gantt.<span class=\"me1\">config<\/span>.<span class=\"me1\">date_format<\/span> <span class=\"sy0\">=<\/span> <span class=\"st0\">&quot;%Y-%m-%d %H:%i&quot;<\/span><span class=\"sy0\">;<\/span> &nbsp; <br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">const<\/span> <span class=\"br0\">&#123;<\/span> tasks <span class=\"br0\">&#125;<\/span> <span class=\"sy0\">=<\/span> <span class=\"kw1\">this<\/span>.<span class=\"me1\">props<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; gantt.<span class=\"me1\">init<\/span><span class=\"br0\">&#40;<\/span><span class=\"kw1\">this<\/span>.<span class=\"me1\">ganttContainer<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; gantt.<span class=\"me1\">parse<\/span><span class=\"br0\">&#40;<\/span>tasks<span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n<br \/>\n&nbsp; &nbsp; render<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp;<span class=\"kw1\">return<\/span> <span class=\"br0\">&#40;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class=\"sy0\">&lt;<\/span>div<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ref<span class=\"sy0\">=<\/span><span class=\"br0\">&#123;<\/span> <span class=\"br0\">&#40;<\/span>input<span class=\"br0\">&#41;<\/span> <span class=\"sy0\">=&gt;<\/span> <span class=\"br0\">&#123;<\/span> <span class=\"kw1\">this<\/span>.<span class=\"me1\">ganttContainer<\/span> <span class=\"sy0\">=<\/span> input <span class=\"br0\">&#125;<\/span> <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; style<span class=\"sy0\">=<\/span><span class=\"br0\">&#123;<\/span> <span class=\"br0\">&#123;<\/span> width<span class=\"sy0\">:<\/span> <span class=\"st0\">'100%'<\/span><span class=\"sy0\">,<\/span> height<span class=\"sy0\">:<\/span> <span class=\"st0\">'100%'<\/span> <span class=\"br0\">&#125;<\/span> <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"sy0\">&gt;&lt;\/<\/span>div<span class=\"sy0\">&gt;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp;<span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><\/div><\/div>\n<p>Then add this code to Gantt.css:<\/p>\n<div class=\"codecolorer-container javascript default codecolorer-noborder\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\">html<span class=\"sy0\">,<\/span> body<span class=\"sy0\">,<\/span> #root<span class=\"sy0\">,<\/span>#root div<span class=\"sy0\">:<\/span>only<span class=\"sy0\">-<\/span>child<span class=\"sy0\">,<\/span> .<span class=\"me1\">gantt<\/span><span class=\"sy0\">-<\/span>container <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; height<span class=\"sy0\">:<\/span> <span class=\"nu0\">100<\/span><span class=\"sy0\">%;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><\/div><\/div>\n<p>And create an index.js file with the following content:<\/p>\n<div class=\"codecolorer-container javascript default codecolorer-noborder\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\"><span class=\"kw5\">import<\/span> Gantt from <span class=\"st0\">'.\/Gantt'<\/span><span class=\"sy0\">;<\/span><br \/>\n<span class=\"kw5\">export<\/span> <span class=\"kw1\">default<\/span> Gantt<span class=\"sy0\">;<\/span><\/div><\/div>\n<p>What we have done here \u2013 we&#8217;ve created a react component that currently serves as a wrapper for dhtmlxGantt js library. dhtmlxGantt itself is a regular JS library that lives outside ReactJS world, thus we created a wrapper component.<br \/>\nOnce our component is mounted, we initialize dhtmlxGantt and attach it to DOM. We can also populate it with the data passed via props. <\/p>\n<p>Note, that since a free version of dhtmlxGantt has no destructor, we do not define the <a href=\"https:\/\/legacy.reactjs.org\/docs\/react-component.html#componentwillunmount\" target=\"_blank\">componentWillUnmount<\/a> method. It 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.<\/p>\n<p>We have also specified the <a href=\"https:\/\/docs.dhtmlx.com\/gantt\/api__gantt_date_format_config.html\" rel=\"noopener\" target=\"_blank\">date_format<\/a> config, which sets the format of dates that will come from the data source so that Gantt could parse them correctly.<\/p>\n<p>The next step is to add Gantt to our App component. Note that we use hard-coded data for this sample:<br \/>\n.\/src\/App.js:<\/p>\n<div class=\"codecolorer-container javascript default codecolorer-noborder\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\"><span class=\"kw5\">import<\/span> React<span class=\"sy0\">,<\/span> <span class=\"br0\">&#123;<\/span> Component <span class=\"br0\">&#125;<\/span> from <span class=\"st0\">'react'<\/span><span class=\"sy0\">;<\/span><br \/>\n<span class=\"kw5\">import<\/span> Gantt from <span class=\"st0\">'.\/components\/Gantt'<\/span><span class=\"sy0\">;<\/span><br \/>\n<span class=\"kw5\">import<\/span> <span class=\"st0\">'.\/App.css'<\/span><span class=\"sy0\">;<\/span><br \/>\n<br \/>\n<span class=\"kw1\">const<\/span> data <span class=\"sy0\">=<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; data<span class=\"sy0\">:<\/span> <span class=\"br0\">&#91;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#123;<\/span> id<span class=\"sy0\">:<\/span> <span class=\"nu0\">1<\/span><span class=\"sy0\">,<\/span> text<span class=\"sy0\">:<\/span> <span class=\"st0\">'Task #1'<\/span><span class=\"sy0\">,<\/span> start_date<span class=\"sy0\">:<\/span> <span class=\"st0\">'2019-04-15'<\/span><span class=\"sy0\">,<\/span> duration<span class=\"sy0\">:<\/span> <span class=\"nu0\">3<\/span><span class=\"sy0\">,<\/span> progress<span class=\"sy0\">:<\/span> <span class=\"nu0\">0.6<\/span> <span class=\"br0\">&#125;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#123;<\/span> id<span class=\"sy0\">:<\/span> <span class=\"nu0\">2<\/span><span class=\"sy0\">,<\/span> text<span class=\"sy0\">:<\/span> <span class=\"st0\">'Task #2'<\/span><span class=\"sy0\">,<\/span> start_date<span class=\"sy0\">:<\/span> <span class=\"st0\">'2019-04-18'<\/span><span class=\"sy0\">,<\/span> duration<span class=\"sy0\">:<\/span> <span class=\"nu0\">3<\/span><span class=\"sy0\">,<\/span> progress<span class=\"sy0\">:<\/span> <span class=\"nu0\">0.4<\/span> <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#93;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; links<span class=\"sy0\">:<\/span> <span class=\"br0\">&#91;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#123;<\/span> id<span class=\"sy0\">:<\/span> <span class=\"nu0\">1<\/span><span class=\"sy0\">,<\/span> source<span class=\"sy0\">:<\/span> <span class=\"nu0\">1<\/span><span class=\"sy0\">,<\/span> target<span class=\"sy0\">:<\/span> <span class=\"nu0\">2<\/span><span class=\"sy0\">,<\/span> type<span class=\"sy0\">:<\/span> <span class=\"st0\">'0'<\/span> <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#93;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><span class=\"sy0\">;<\/span><br \/>\n<span class=\"kw5\">class<\/span> App <span class=\"kw5\">extends<\/span> Component <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; render<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">return<\/span> <span class=\"br0\">&#40;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"sy0\">&lt;<\/span>div<span class=\"sy0\">&gt;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"sy0\">&lt;<\/span>div className<span class=\"sy0\">=<\/span><span class=\"st0\">&quot;gantt-container&quot;<\/span><span class=\"sy0\">&gt;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"sy0\">&lt;<\/span>Gantt tasks<span class=\"sy0\">=<\/span><span class=\"br0\">&#123;<\/span>data<span class=\"br0\">&#125;<\/span><span class=\"sy0\">\/&gt;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"sy0\">&lt;\/<\/span>div<span class=\"sy0\">&gt;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"sy0\">&lt;\/<\/span>div<span class=\"sy0\">&gt;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><br \/>\n<span class=\"kw5\">export<\/span> <span class=\"kw1\">default<\/span> App<span class=\"sy0\">;<\/span><\/div><\/div>\n<p>If we run the app now, we should see a Gantt chart with initial tasks on a page:<\/p>\n<div class=\"codecolorer-container javascript default codecolorer-noborder\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\">yarn start<\/div><\/div>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/dhtmlx.com\/blog\/wp-content\/uploads\/2017\/05\/react-gantt-chart900.png\" alt=\"react gantt chart\" width=\"900\" height=\"360\" class=\"aligncenter size-full wp-image-6202\" srcset=\"https:\/\/dhtmlx.com\/blog\/wp-content\/uploads\/2017\/05\/react-gantt-chart900.png 900w, https:\/\/dhtmlx.com\/blog\/wp-content\/uploads\/2017\/05\/react-gantt-chart900-300x120.png 300w, https:\/\/dhtmlx.com\/blog\/wp-content\/uploads\/2017\/05\/react-gantt-chart900-768x307.png 768w\" sizes=\"auto, (max-width: 900px) 100vw, 900px\" \/><\/p>\n<h4>Configuring Gantt chart <\/h4>\n<p>Let us explore the API of the component a bit more. If you complement an app with the Gantt chart, at some moment the client will ask you to add the ability to zoom the time scale of the Gantt chart. <\/p>\n<p>How it&#8217;s usually done: <\/p>\n<ul>\n<li>the time scale of dhtmlxGantt is defined by a <a href=\"https:\/\/docs.dhtmlx.com\/gantt\/desktop__configuring_time_scale.html\" target=\"_blank\">number of settings<\/a>, such as number of rows, time step of each row, format of labels, etc.<\/li>\n<li>these settings can be changed <a href=\"https:\/\/docs.dhtmlx.com\/gantt\/desktop__dynamic_scale.html\" target=\"_blank\">dynamically<\/a> <\/li>\n<li>adittionally, there is a special <a href=\"https:\/\/docs.dhtmlx.com\/gantt\/desktop__zooming.html\" rel=\"noopener\" target=\"_blank\">API for zoom levels<\/a> of the time scale<\/li>\n<\/ul>\n<p>So you need to define several configuration presets for different zoom levels (minutes\/hours\/days\/months\/&#8230;) and give a user some kind of UI, <a href=\"https:\/\/docs.dhtmlx.com\/gantt\/samples\/03_scales\/05_dynamic_scales.html\" target=\"_blank\">usually a toggle or a slider<\/a>, to switch between them. <\/p>\n<p>We can implement it in React using <a href=\"https:\/\/docs.dhtmlx.com\/gantt\/desktop__zooming.html\" rel=\"noopener\" target=\"_blank\">zooming API<\/a>. Firstly, we implement a couple of presets for time scale configuration in the Gantt component.<\/p>\n<p>Open Gantt.js. to add the following function to it:<\/p>\n<div class=\"codecolorer-container javascript default codecolorer-noborder\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\">initZoom<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; gantt.<span class=\"me1\">ext<\/span>.<span class=\"me1\">zoom<\/span>.<span class=\"me1\">init<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; levels<span class=\"sy0\">:<\/span> <span class=\"br0\">&#91;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; name<span class=\"sy0\">:<\/span> <span class=\"st0\">'Hours'<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; scale_height<span class=\"sy0\">:<\/span> <span class=\"nu0\">60<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; min_column_width<span class=\"sy0\">:<\/span> <span class=\"nu0\">30<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; scales<span class=\"sy0\">:<\/span> <span class=\"br0\">&#91;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#123;<\/span> unit<span class=\"sy0\">:<\/span> <span class=\"st0\">'day'<\/span><span class=\"sy0\">,<\/span> step<span class=\"sy0\">:<\/span> <span class=\"nu0\">1<\/span><span class=\"sy0\">,<\/span> format<span class=\"sy0\">:<\/span> <span class=\"st0\">'%d %M'<\/span> <span class=\"br0\">&#125;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#123;<\/span> unit<span class=\"sy0\">:<\/span> <span class=\"st0\">'hour'<\/span><span class=\"sy0\">,<\/span> step<span class=\"sy0\">:<\/span> <span class=\"nu0\">1<\/span><span class=\"sy0\">,<\/span> format<span class=\"sy0\">:<\/span> <span class=\"st0\">'%H'<\/span> <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#93;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; name<span class=\"sy0\">:<\/span> <span class=\"st0\">'Days'<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; scale_height<span class=\"sy0\">:<\/span> <span class=\"nu0\">60<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; min_column_width<span class=\"sy0\">:<\/span> <span class=\"nu0\">70<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; scales<span class=\"sy0\">:<\/span> <span class=\"br0\">&#91;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#123;<\/span> unit<span class=\"sy0\">:<\/span> <span class=\"st0\">'week'<\/span><span class=\"sy0\">,<\/span> step<span class=\"sy0\">:<\/span> <span class=\"nu0\">1<\/span><span class=\"sy0\">,<\/span> format<span class=\"sy0\">:<\/span> <span class=\"st0\">'Week #%W'<\/span> <span class=\"br0\">&#125;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#123;<\/span> unit<span class=\"sy0\">:<\/span> <span class=\"st0\">'day'<\/span><span class=\"sy0\">,<\/span> step<span class=\"sy0\">:<\/span> <span class=\"nu0\">1<\/span><span class=\"sy0\">,<\/span> format<span class=\"sy0\">:<\/span> <span class=\"st0\">'%d %M'<\/span> <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#93;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; name<span class=\"sy0\">:<\/span> <span class=\"st0\">'Months'<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; scale_height<span class=\"sy0\">:<\/span> <span class=\"nu0\">60<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; min_column_width<span class=\"sy0\">:<\/span> <span class=\"nu0\">70<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; scales<span class=\"sy0\">:<\/span> <span class=\"br0\">&#91;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#123;<\/span> unit<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;month&quot;<\/span><span class=\"sy0\">,<\/span> step<span class=\"sy0\">:<\/span> <span class=\"nu0\">1<\/span><span class=\"sy0\">,<\/span> format<span class=\"sy0\">:<\/span> <span class=\"st0\">'%F'<\/span> <span class=\"br0\">&#125;<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#123;<\/span> unit<span class=\"sy0\">:<\/span> <span class=\"st0\">'week'<\/span><span class=\"sy0\">,<\/span> step<span class=\"sy0\">:<\/span> <span class=\"nu0\">1<\/span><span class=\"sy0\">,<\/span> format<span class=\"sy0\">:<\/span> <span class=\"st0\">'#%W'<\/span> <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#93;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#93;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><\/div><\/div>\n<p>Here we&#8217;ve defined all levels of zoom that will be available in our Gantt. Each level has its own name which will be used to activate it.<br \/>\nThen we need the following code to activate zoom levels:<\/p>\n<div class=\"codecolorer-container javascript default codecolorer-noborder\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\">setZoom<span class=\"br0\">&#40;<\/span>value<span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">if<\/span><span class=\"br0\">&#40;<\/span><span class=\"sy0\">!<\/span>gantt.$initialized<span class=\"br0\">&#41;<\/span><span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">this<\/span>.<span class=\"me1\">initZoom<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; gantt.<span class=\"me1\">ext<\/span>.<span class=\"me1\">zoom<\/span>.<span class=\"me1\">setLevel<\/span><span class=\"br0\">&#40;<\/span>value<span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><br \/>\n<br \/>\nshouldComponentUpdate<span class=\"br0\">&#40;<\/span>nextProps<span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">return<\/span> <span class=\"kw1\">this<\/span>.<span class=\"me1\">props<\/span>.<span class=\"me1\">zoom<\/span> <span class=\"sy0\">!==<\/span> nextProps.<span class=\"me1\">zoom<\/span><span class=\"sy0\">;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><\/div><\/div>\n<p>Bear in mind that repainting of Gantt is quite a costly procedure, we\u2019ll make sure that it\u2019ll be called only when it\u2019s needed by checking whether props have actually changed in <a href=\"https:\/\/legacy.reactjs.org\/docs\/react-component.html#shouldcomponentupdate\" rel=\"noopener\" target=\"_blank\">shouldComponentUpdate<\/a>.<\/p>\n<p>And add the <strong>setZoom<\/strong> call at the beginning of the <strong>render<\/strong> function of the component:<\/p>\n<div class=\"codecolorer-container javascript default codecolorer-noborder\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\">render<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">const<\/span> <span class=\"br0\">&#123;<\/span> zoom <span class=\"br0\">&#125;<\/span> <span class=\"sy0\">=<\/span> <span class=\"kw1\">this<\/span>.<span class=\"me1\">props<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">this<\/span>.<span class=\"me1\">setZoom<\/span><span class=\"br0\">&#40;<\/span>zoom<span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">return<\/span> <span class=\"br0\">&#40;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"sy0\">&lt;<\/span>div<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; ref<span class=\"sy0\">=<\/span><span class=\"br0\">&#123;<\/span><span class=\"br0\">&#40;<\/span>input<span class=\"br0\">&#41;<\/span> <span class=\"sy0\">=&gt;<\/span> <span class=\"br0\">&#123;<\/span> <span class=\"kw1\">this<\/span>.<span class=\"me1\">ganttContainer<\/span> <span class=\"sy0\">=<\/span> input <span class=\"br0\">&#125;<\/span><span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; style<span class=\"sy0\">=<\/span><span class=\"br0\">&#123;<\/span><span class=\"br0\">&#123;<\/span> width<span class=\"sy0\">:<\/span> <span class=\"st0\">'100%'<\/span><span class=\"sy0\">,<\/span> height<span class=\"sy0\">:<\/span> <span class=\"st0\">'100%'<\/span> <span class=\"br0\">&#125;<\/span><span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"sy0\">&gt;&lt;\/<\/span>div<span class=\"sy0\">&gt;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><\/div><\/div>\n<p>The zoom plugin must be initialized by <strong><a href=\"https:\/\/docs.dhtmlx.com\/gantt\/desktop__zooming.html\" rel=\"noopener\" target=\"_blank\">gantt.ext.zoom.init<\/a><\/strong> call before the first usage.<\/p>\n<p>Each time we call <strong>gantt.ext.zoom.setLevel<\/strong>, it will apply the specified zoom level and call the <strong>gantt.render()<\/strong> function to repaint the Gantt and apply changes. Thus, we don\u2019t call this function explicitly in our code.<\/p>\n<p>If we don&#8217;t use the Zoom plugin and change the Gantt configuration manually, it will be needed to add call Gantt repaint from the <strong>componentDidUpdate<\/strong> hook:<\/p>\n<div class=\"codecolorer-container javascript default codecolorer-noborder\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\">componentDidUpdate<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; gantt.<span class=\"me1\">render<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><\/div><\/div>\n<p>Other than that, everything should be straightforward. <strong>setLevel<\/strong> is called for the first time before Gantt is rendered on a page, so we use this moment to initialize our zoom settings:<\/p>\n<div class=\"codecolorer-container javascript default codecolorer-noborder\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\">setZoom<span class=\"br0\">&#40;<\/span>value<span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">if<\/span><span class=\"br0\">&#40;<\/span><span class=\"sy0\">!<\/span>gantt.$initialized<span class=\"br0\">&#41;<\/span><span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; <span class=\"kw1\">this<\/span>.<span class=\"me1\">initZoom<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; gantt.<span class=\"me1\">ext<\/span>.<span class=\"me1\">zoom<\/span>.<span class=\"me1\">setLevel<\/span><span class=\"br0\">&#40;<\/span>value<span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><\/div><\/div>\n<p>Now Gantt chart scales should be defined with the <strong>zoom<\/strong> property. If this property is changed we should call the <strong>render<\/strong> function to redraw Gantt with new scales.<\/p>\n<p>Now, let us add UI for selecting a zoom level. We&#8217;ll go with a simple toolbar and toggles.<\/p>\n<p>Create the Toolbar component:<\/p>\n<p><em>src\/components\/Toolbar\/index.js:<\/em><\/p>\n<div class=\"codecolorer-container javascript default codecolorer-noborder\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\"><span class=\"kw5\">import<\/span> Toolbar from <span class=\"st0\">'.\/Toolbar'<\/span><span class=\"sy0\">;<\/span><br \/>\n<span class=\"kw5\">export<\/span> <span class=\"kw1\">default<\/span> Toolbar<span class=\"sy0\">;<\/span><\/div><\/div>\n<p><em>src\/components\/Toolbar\/Toolbar.js:<\/em><\/p>\n<div class=\"codecolorer-container javascript default codecolorer-noborder\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\"><span class=\"kw5\">import<\/span> React<span class=\"sy0\">,<\/span> <span class=\"br0\">&#123;<\/span> Component <span class=\"br0\">&#125;<\/span> from <span class=\"st0\">'react'<\/span><span class=\"sy0\">;<\/span><br \/>\n<span class=\"kw5\">export<\/span> <span class=\"kw1\">default<\/span> <span class=\"kw5\">class<\/span> Toolbar <span class=\"kw5\">extends<\/span> Component <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; handleZoomChange <span class=\"sy0\">=<\/span> <span class=\"br0\">&#40;<\/span>e<span class=\"br0\">&#41;<\/span> <span class=\"sy0\">=&gt;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span><span class=\"kw1\">this<\/span>.<span class=\"me1\">props<\/span>.<span class=\"me1\">onZoomChange<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">this<\/span>.<span class=\"me1\">props<\/span>.<span class=\"me1\">onZoomChange<\/span><span class=\"br0\">&#40;<\/span>e.<span class=\"me1\">target<\/span>.<span class=\"me1\">value<\/span><span class=\"br0\">&#41;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; render<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">const<\/span> zoomRadios <span class=\"sy0\">=<\/span> <span class=\"br0\">&#91;<\/span><span class=\"st0\">'Hours'<\/span><span class=\"sy0\">,<\/span> <span class=\"st0\">'Days'<\/span><span class=\"sy0\">,<\/span> <span class=\"st0\">'Months'<\/span><span class=\"br0\">&#93;<\/span>.<span class=\"me1\">map<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#40;<\/span>value<span class=\"br0\">&#41;<\/span> <span class=\"sy0\">=&gt;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">const<\/span> isActive <span class=\"sy0\">=<\/span> <span class=\"kw1\">this<\/span>.<span class=\"me1\">props<\/span>.<span class=\"me1\">zoom<\/span> <span class=\"sy0\">===<\/span> value<span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">return<\/span> <span class=\"br0\">&#40;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"sy0\">&lt;<\/span>label key<span class=\"sy0\">=<\/span><span class=\"br0\">&#123;<\/span> value <span class=\"br0\">&#125;<\/span> className<span class=\"sy0\">=<\/span><span class=\"br0\">&#123;<\/span> `radio<span class=\"sy0\">-<\/span>label $<span class=\"br0\">&#123;<\/span>isActive <span class=\"sy0\">?<\/span> <span class=\"st0\">'radio-label-active'<\/span><span class=\"sy0\">:<\/span> <span class=\"st0\">''<\/span><span class=\"br0\">&#125;<\/span>` <span class=\"br0\">&#125;<\/span><span class=\"sy0\">&gt;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"sy0\">&lt;<\/span>input type<span class=\"sy0\">=<\/span><span class=\"st0\">'radio'<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; checked<span class=\"sy0\">=<\/span><span class=\"br0\">&#123;<\/span> isActive <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; onChange<span class=\"sy0\">=<\/span><span class=\"br0\">&#123;<\/span> <span class=\"kw1\">this<\/span>.<span class=\"me1\">handleZoomChange<\/span> <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; value<span class=\"sy0\">=<\/span><span class=\"br0\">&#123;<\/span> value <span class=\"br0\">&#125;<\/span><span class=\"sy0\">\/&gt;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#123;<\/span> value <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"sy0\">&lt;\/<\/span>label<span class=\"sy0\">&gt;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">return<\/span> <span class=\"br0\">&#40;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"sy0\">&lt;<\/span>div className<span class=\"sy0\">=<\/span><span class=\"st0\">&quot;tool-bar&quot;<\/span><span class=\"sy0\">&gt;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"sy0\">&lt;<\/span>b<span class=\"sy0\">&gt;<\/span>Zooming<span class=\"sy0\">:<\/span> <span class=\"sy0\">&lt;\/<\/span>b<span class=\"sy0\">&gt;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#123;<\/span> zoomRadios <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"sy0\">&lt;\/<\/span>div<span class=\"sy0\">&gt;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><\/div><\/div>\n<p>As you can see it is quite plain &#8211; we add a group of radio buttons and provide onZoomChange <a href=\"https:\/\/legacy.reactjs.org\/docs\/lifting-state-up.html\" target=\"_blank\">handler for a parent component<\/a>.<\/p>\n<p>Here we add a toolbar to the App component:<\/p>\n<div class=\"codecolorer-container javascript default codecolorer-noborder\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\"><span class=\"kw5\">import<\/span> Toolbar from <span class=\"st0\">'.\/components\/Toolbar'<\/span><span class=\"sy0\">;<\/span><\/div><\/div>\n<p>and a handler for the <strong>change<\/strong> event:<\/p>\n<div class=\"codecolorer-container javascript default codecolorer-noborder\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\">state <span class=\"sy0\">=<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; currentZoom<span class=\"sy0\">:<\/span> <span class=\"st0\">'Days'<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp;<br \/>\nhandleZoomChange <span class=\"sy0\">=<\/span> <span class=\"br0\">&#40;<\/span>zoom<span class=\"br0\">&#41;<\/span> <span class=\"sy0\">=&gt;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">this<\/span>.<span class=\"me1\">setState<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; currentZoom<span class=\"sy0\">:<\/span> zoom<br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><\/div><\/div>\n<p>JSX:<\/p>\n<div class=\"codecolorer-container javascript default codecolorer-noborder\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\">render<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">const<\/span> <span class=\"br0\">&#123;<\/span> currentZoom <span class=\"br0\">&#125;<\/span> <span class=\"sy0\">=<\/span> <span class=\"kw1\">this<\/span>.<span class=\"me1\">state<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">return<\/span> <span class=\"br0\">&#40;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"sy0\">&lt;<\/span>div<span class=\"sy0\">&gt;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"sy0\">&lt;<\/span>div className<span class=\"sy0\">=<\/span><span class=\"st0\">&quot;zoom-bar&quot;<\/span><span class=\"sy0\">&gt;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"sy0\">&lt;<\/span>Toolbar<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; zoom<span class=\"sy0\">=<\/span><span class=\"br0\">&#123;<\/span>currentZoom<span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; onZoomChange<span class=\"sy0\">=<\/span><span class=\"br0\">&#123;<\/span><span class=\"kw1\">this<\/span>.<span class=\"me1\">handleZoomChange<\/span><span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"sy0\">\/&gt;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"sy0\">&lt;\/<\/span>div<span class=\"sy0\">&gt;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"sy0\">&lt;<\/span>div className<span class=\"sy0\">=<\/span><span class=\"st0\">&quot;gantt-container&quot;<\/span><span class=\"sy0\">&gt;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"sy0\">&lt;<\/span>Gantt<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; tasks<span class=\"sy0\">=<\/span><span class=\"br0\">&#123;<\/span>data<span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; zoom<span class=\"sy0\">=<\/span><span class=\"br0\">&#123;<\/span>currentZoom<span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"sy0\">\/&gt;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"sy0\">&lt;\/<\/span>div<span class=\"sy0\">&gt;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"sy0\">&lt;\/<\/span>div<span class=\"sy0\">&gt;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><\/div><\/div>\n<p>Now, each time a user selects a specific zoom level in a toolbar, changes will be captured by the App, which will then pass an updated state to our Gantt.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/dhtmlx.com\/blog\/wp-content\/uploads\/2017\/05\/react-gantt-1.png\" alt=\"react gantt\" width=\"1496\" height=\"591\" class=\"aligncenter size-full wp-image-6194\" srcset=\"https:\/\/dhtmlx.com\/blog\/wp-content\/uploads\/2017\/05\/react-gantt-1.png 1496w, https:\/\/dhtmlx.com\/blog\/wp-content\/uploads\/2017\/05\/react-gantt-1-300x119.png 300w, https:\/\/dhtmlx.com\/blog\/wp-content\/uploads\/2017\/05\/react-gantt-1-768x303.png 768w, https:\/\/dhtmlx.com\/blog\/wp-content\/uploads\/2017\/05\/react-gantt-1-1024x405.png 1024w\" sizes=\"auto, (max-width: 1496px) 100vw, 1496px\" \/><\/p>\n<h4>Processing Changes Made in Gantt<\/h4>\n<p>What else would you need while adding a Gantt chart to your app? Most probably you&#8217;ll need to do something with changes that users make in a Gantt chart &#8211; send changes to the backend or update other components.<\/p>\n<p>In this tutorial, we won&#8217;t cover saving changes to the database. Instead, we&#8217;ll show how to capture these changes, and then pass them somewhere in the app.<\/p>\n<p>You can capture Gantt changes using a special <a href=\"https:\/\/docs.dhtmlx.com\/gantt\/desktop__server_side.html#technique\" rel=\"noopener\" target=\"_blank\">dataProcessor<\/a> module, embedded into dhtmlxGantt. It can serve as a way for tracking user actions inside Gantt.<\/p>\n<p>Here is how it can be used. Open <em>src\/components\/Gantt\/Gantt.js<\/em> and add the following method:<\/p>\n<div class=\"codecolorer-container javascript default codecolorer-noborder\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\">initGanttDataProcessor<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">const<\/span> onDataUpdated <span class=\"sy0\">=<\/span> <span class=\"kw1\">this<\/span>.<span class=\"me1\">props<\/span>.<span class=\"me1\">onDataUpdated<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">this<\/span>.<span class=\"me1\">dataProcessor<\/span> <span class=\"sy0\">=<\/span> gantt.<span class=\"me1\">createDataProcessor<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#40;<\/span>entityType<span class=\"sy0\">,<\/span> action<span class=\"sy0\">,<\/span> item<span class=\"sy0\">,<\/span> id<span class=\"br0\">&#41;<\/span> <span class=\"sy0\">=&gt;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">return<\/span> <span class=\"kw1\">new<\/span> Promise<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#40;<\/span>resolve<span class=\"sy0\">,<\/span> reject<span class=\"br0\">&#41;<\/span> <span class=\"sy0\">=&gt;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span>onDataUpdated<span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; onDataUpdated<span class=\"br0\">&#40;<\/span>entityType<span class=\"sy0\">,<\/span> action<span class=\"sy0\">,<\/span> item<span class=\"sy0\">,<\/span> id<span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">return<\/span> resolve<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><br \/>\ncomponentWillUnmount<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span><span class=\"kw1\">this<\/span>.<span class=\"me1\">dataProcessor<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">this<\/span>.<span class=\"me1\">dataProcessor<\/span>.<span class=\"me1\">destructor<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">this<\/span>.<span class=\"me1\">dataProcessor<\/span> <span class=\"sy0\">=<\/span> <span class=\"kw2\">null<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><\/div><\/div>\n<p>Also update the <strong>componentDidMount<\/strong> method:<\/p>\n<div class=\"codecolorer-container javascript default codecolorer-noborder\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\">componentDidMount<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; gantt.<span class=\"me1\">config<\/span>.<span class=\"me1\">date_format<\/span> <span class=\"sy0\">=<\/span> <span class=\"st0\">&quot;%Y-%m-%d %H:%i&quot;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">this<\/span>.<span class=\"me1\">initGanttDataProcessor<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">const<\/span> <span class=\"br0\">&#123;<\/span> tasks <span class=\"br0\">&#125;<\/span> <span class=\"sy0\">=<\/span> <span class=\"kw1\">this<\/span>.<span class=\"me1\">props<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; gantt.<span class=\"me1\">init<\/span><span class=\"br0\">&#40;<\/span><span class=\"kw1\">this<\/span>.<span class=\"me1\">ganttContainer<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; gantt.<span class=\"me1\">parse<\/span><span class=\"br0\">&#40;<\/span>tasks<span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><\/div><\/div>\n<p>That&#8217;s how we can capture all changes made in Gantt and send them to the parent component.<\/p>\n<p>We also save the <strong>dataProcessor<\/strong> instance returned from <strong>createDataProcessor<\/strong> and clean it up in <strong>componentWillUnmount<\/strong>. <\/p>\n<p>Now update the App component &#8211; what we want to do here is to simply catch events, create descriptive messages for them and put those messages into the local state:<\/p>\n<div class=\"codecolorer-container javascript default codecolorer-noborder\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\">state <span class=\"sy0\">=<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; currentZoom<span class=\"sy0\">:<\/span> <span class=\"st0\">'Days'<\/span><span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; messages<span class=\"sy0\">:<\/span> <span class=\"br0\">&#91;<\/span><span class=\"br0\">&#93;<\/span><span class=\"sy0\">,<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><span class=\"sy0\">;<\/span><br \/>\naddMessage<span class=\"br0\">&#40;<\/span>message<span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">const<\/span> maxLogLength <span class=\"sy0\">=<\/span> <span class=\"nu0\">5<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">const<\/span> newMessage <span class=\"sy0\">=<\/span> <span class=\"br0\">&#123;<\/span> message <span class=\"br0\">&#125;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">const<\/span> messages <span class=\"sy0\">=<\/span> <span class=\"br0\">&#91;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; newMessage<span class=\"sy0\">,<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; ...<span class=\"kw1\">this<\/span>.<span class=\"me1\">state<\/span>.<span class=\"me1\">messages<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#93;<\/span><span class=\"sy0\">;<\/span><br \/>\n<br \/>\n&nbsp; &nbsp; <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span>messages.<span class=\"me1\">length<\/span> <span class=\"sy0\">&gt;<\/span> maxLogLength<span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; messages.<span class=\"me1\">length<\/span> <span class=\"sy0\">=<\/span> maxLogLength<span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">this<\/span>.<span class=\"me1\">setState<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#123;<\/span> messages <span class=\"br0\">&#125;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><br \/>\n<br \/>\nlogDataUpdate <span class=\"sy0\">=<\/span> <span class=\"br0\">&#40;<\/span>entityType<span class=\"sy0\">,<\/span> action<span class=\"sy0\">,<\/span> itemData<span class=\"sy0\">,<\/span> id<span class=\"br0\">&#41;<\/span> <span class=\"sy0\">=&gt;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; let text <span class=\"sy0\">=<\/span> itemData <span class=\"sy0\">&amp;&amp;<\/span> itemData.<span class=\"me1\">text<\/span> <span class=\"sy0\">?<\/span> ` <span class=\"br0\">&#40;<\/span>$<span class=\"br0\">&#123;<\/span>itemData.<span class=\"me1\">text<\/span><span class=\"br0\">&#125;<\/span><span class=\"br0\">&#41;<\/span>`<span class=\"sy0\">:<\/span> <span class=\"st0\">''<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; let message <span class=\"sy0\">=<\/span> `$<span class=\"br0\">&#123;<\/span>entityType<span class=\"br0\">&#125;<\/span> $<span class=\"br0\">&#123;<\/span>action<span class=\"br0\">&#125;<\/span><span class=\"sy0\">:<\/span> $<span class=\"br0\">&#123;<\/span>id<span class=\"br0\">&#125;<\/span> $<span class=\"br0\">&#123;<\/span>text<span class=\"br0\">&#125;<\/span>`<span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span>entityType <span class=\"sy0\">===<\/span> <span class=\"st0\">'link'<\/span> <span class=\"sy0\">&amp;&amp;<\/span> action <span class=\"sy0\">!==<\/span> <span class=\"st0\">'delete'<\/span> <span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; message <span class=\"sy0\">+=<\/span> ` <span class=\"br0\">&#40;<\/span> source<span class=\"sy0\">:<\/span> $<span class=\"br0\">&#123;<\/span>itemData.<span class=\"me1\">source<\/span><span class=\"br0\">&#125;<\/span><span class=\"sy0\">,<\/span> target<span class=\"sy0\">:<\/span> $<span class=\"br0\">&#123;<\/span>itemData.<span class=\"me1\">target<\/span><span class=\"br0\">&#125;<\/span> <span class=\"br0\">&#41;<\/span>`<span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">this<\/span>.<span class=\"me1\">addMessage<\/span><span class=\"br0\">&#40;<\/span>message<span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><\/div><\/div>\n<p>After that, it is necessary to set a component that will display these messages on a page.<br \/>\nFirst of all, create a new folder <em>src\/components\/MessageArea<\/em>, we&#8217;ll define all files of the component there.<\/p>\n<p>Add a file <em>src\/components\/MessageArea\/MessageArea.js<\/em> and define the component. We don&#8217;t need anything too fancy, our message area will show the data using basic html list:<\/p>\n<div class=\"codecolorer-container javascript default codecolorer-noborder\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\"><span class=\"kw5\">import<\/span> React<span class=\"sy0\">,<\/span> <span class=\"br0\">&#123;<\/span> Component <span class=\"br0\">&#125;<\/span> from <span class=\"st0\">'react'<\/span><span class=\"sy0\">;<\/span><br \/>\n<br \/>\n<span class=\"kw5\">export<\/span> <span class=\"kw1\">default<\/span> <span class=\"kw5\">class<\/span> MessageArea <span class=\"kw5\">extends<\/span> Component <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; render<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">const<\/span> messages <span class=\"sy0\">=<\/span> <span class=\"kw1\">this<\/span>.<span class=\"me1\">props<\/span>.<span class=\"me1\">messages<\/span>.<span class=\"me1\">map<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#123;<\/span> message <span class=\"br0\">&#125;<\/span><span class=\"br0\">&#41;<\/span> <span class=\"sy0\">=&gt;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">return<\/span> <span class=\"sy0\">&lt;<\/span>li key<span class=\"sy0\">=<\/span><span class=\"br0\">&#123;<\/span> <span class=\"kw4\">Math<\/span>.<span class=\"me1\">random<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#125;<\/span><span class=\"sy0\">&gt;<\/span><span class=\"br0\">&#123;<\/span>message<span class=\"br0\">&#125;<\/span><span class=\"sy0\">&lt;\/<\/span>li<span class=\"sy0\">&gt;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">return<\/span> <span class=\"br0\">&#40;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"sy0\">&lt;<\/span>div className<span class=\"sy0\">=<\/span><span class=\"st0\">&quot;message-area&quot;<\/span><span class=\"sy0\">&gt;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"sy0\">&lt;<\/span>h3<span class=\"sy0\">&gt;<\/span>Messages<span class=\"sy0\">:&lt;\/<\/span>h3<span class=\"sy0\">&gt;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"sy0\">&lt;<\/span>ul<span class=\"sy0\">&gt;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#123;<\/span> messages <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"sy0\">&lt;\/<\/span>ul<span class=\"sy0\">&gt;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"sy0\">&lt;\/<\/span>div<span class=\"sy0\">&gt;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><br \/>\n<br \/>\nMessageArea.<span class=\"me1\">defaultProps<\/span> <span class=\"sy0\">=<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; messages<span class=\"sy0\">:<\/span> <span class=\"br0\">&#91;<\/span><span class=\"br0\">&#93;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><span class=\"sy0\">;<\/span><\/div><\/div>\n<p>To display the message, you need to change the height of the gantt-container. For this purpose, you have to update the Gantt.css file with the following code:<\/p>\n<div class=\"codecolorer-container javascript default codecolorer-noborder\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\">.<span class=\"me1\">gantt<\/span><span class=\"sy0\">-<\/span>container <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; height<span class=\"sy0\">:<\/span> calc<span class=\"br0\">&#40;<\/span>100vh <span class=\"sy0\">-<\/span> 50px <span class=\"sy0\">-<\/span> 200px<span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><\/div><\/div>\n<p>Add styles for the message area:<br \/>\n<em>src\/components\/MessageArea\/MessageArea.css<\/em>:<\/p>\n<div class=\"codecolorer-container javascript default codecolorer-noborder\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\">.<span class=\"me1\">message<\/span><span class=\"sy0\">-<\/span>area <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; background<span class=\"sy0\">:<\/span> #ebebeb<span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; height<span class=\"sy0\">:<\/span> 200px<span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; overflow<span class=\"sy0\">:<\/span> auto<span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; padding<span class=\"sy0\">:<\/span> 10px<span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; box<span class=\"sy0\">-<\/span>sizing<span class=\"sy0\">:<\/span>border<span class=\"sy0\">-<\/span>box<span class=\"sy0\">;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><br \/>\n.<span class=\"me1\">message<\/span><span class=\"sy0\">-<\/span>area ul<span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; margin<span class=\"sy0\">:<\/span> <span class=\"nu0\">0<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; padding<span class=\"sy0\">:<\/span> <span class=\"nu0\">0<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; list<span class=\"sy0\">-<\/span>style<span class=\"sy0\">:<\/span> none<span class=\"sy0\">;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><br \/>\n.<span class=\"me1\">message<\/span><span class=\"sy0\">-<\/span>area li<span class=\"sy0\">:<\/span>before <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; content<span class=\"sy0\">:<\/span> <span class=\"st0\">&quot;<span class=\"es0\">\\0<\/span>03e&quot;<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; padding<span class=\"sy0\">-<\/span>right<span class=\"sy0\">:<\/span> 10px<span class=\"sy0\">;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><\/div><\/div>\n<p>Then create another file <em>src\/components\/MessageArea\/index.js<\/em>, which will be the point of import for this component:<\/p>\n<div class=\"codecolorer-container javascript default codecolorer-noborder\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\"><span class=\"kw5\">import<\/span> MessageArea from <span class=\"st0\">'.\/MessageArea'<\/span><span class=\"sy0\">;<\/span><br \/>\n<span class=\"kw5\">import<\/span> <span class=\"st0\">'.\/MessageArea.css'<\/span><span class=\"sy0\">;<\/span><br \/>\n<span class=\"kw5\">export<\/span> <span class=\"kw1\">default<\/span> MessageArea<span class=\"sy0\">;<\/span><\/div><\/div>\n<p>And finally, connect this component to the App. Note that we&#8217;ve created \/MessageArea\/index.js specificly to simplify the import of this component. MessageArea may consist of multiple files, yet we import them via index.js as one module:<br \/>\nimports:<\/p>\n<div class=\"codecolorer-container javascript default codecolorer-noborder\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\"><span class=\"kw5\">import<\/span> MessageArea from <span class=\"st0\">'.\/components\/MessageArea'<\/span><span class=\"sy0\">;<\/span><\/div><\/div>\n<p>JSX:<\/p>\n<div class=\"codecolorer-container javascript default codecolorer-noborder\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"javascript codecolorer\">render<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span> &nbsp;<br \/>\n&nbsp; &nbsp; <span class=\"kw1\">const<\/span> <span class=\"br0\">&#123;<\/span> currentZoom<span class=\"sy0\">,<\/span> messages <span class=\"br0\">&#125;<\/span> <span class=\"sy0\">=<\/span> <span class=\"kw1\">this<\/span>.<span class=\"me1\">state<\/span><span class=\"sy0\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">return<\/span> <span class=\"br0\">&#40;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"sy0\">&lt;<\/span>div<span class=\"sy0\">&gt;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"sy0\">&lt;<\/span>Toolbar<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; zoom<span class=\"sy0\">=<\/span><span class=\"br0\">&#123;<\/span> currentZoom <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; onZoomChange<span class=\"sy0\">=<\/span><span class=\"br0\">&#123;<\/span> <span class=\"kw1\">this<\/span>.<span class=\"me1\">handleZoomChange<\/span> <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"sy0\">\/&gt;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"sy0\">&lt;<\/span>div className<span class=\"sy0\">=<\/span><span class=\"st0\">&quot;gantt-container&quot;<\/span><span class=\"sy0\">&gt;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"sy0\">&lt;<\/span>Gantt<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; tasks<span class=\"sy0\">=<\/span><span class=\"br0\">&#123;<\/span> data <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; zoom<span class=\"sy0\">=<\/span><span class=\"br0\">&#123;<\/span> currentZoom <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; onDataUpdated <span class=\"sy0\">=<\/span><span class=\"br0\">&#123;<\/span> <span class=\"kw1\">this<\/span>.<span class=\"me1\">logDataUpdate<\/span> <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"sy0\">\/&gt;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"sy0\">&lt;\/<\/span>div<span class=\"sy0\">&gt;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"sy0\">&lt;<\/span>MessageArea<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; messages<span class=\"sy0\">=<\/span><span class=\"br0\">&#123;<\/span> messages <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"sy0\">\/&gt;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"sy0\">&lt;\/<\/span>div<span class=\"sy0\">&gt;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#41;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><\/div><\/div>\n<p>How everything works now \u2013 each time a user changes something in Gantt, we call the promise handler in the App component and update MessageArea, which prints action details on the page. It&#8217;s exactly what we wanted.<\/p>\n<p>If we run the app now and change some tasks or links, we should see appropriate messages under the Gantt chart.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/dhtmlx.com\/blog\/wp-content\/uploads\/2017\/05\/reactjs-gantt-chart-1.png\" alt=\"reactjs gantt chart\" width=\"1600\" height=\"739\" class=\"aligncenter size-full wp-image-6196\" srcset=\"https:\/\/dhtmlx.com\/blog\/wp-content\/uploads\/2017\/05\/reactjs-gantt-chart-1.png 1600w, https:\/\/dhtmlx.com\/blog\/wp-content\/uploads\/2017\/05\/reactjs-gantt-chart-1-300x139.png 300w, https:\/\/dhtmlx.com\/blog\/wp-content\/uploads\/2017\/05\/reactjs-gantt-chart-1-768x355.png 768w, https:\/\/dhtmlx.com\/blog\/wp-content\/uploads\/2017\/05\/reactjs-gantt-chart-1-1024x473.png 1024w\" sizes=\"auto, (max-width: 1600px) 100vw, 1600px\" \/><\/p>\n<p><strong><a href=\"https:\/\/github.com\/DHTMLX\/react-gantt-demo\" target=\"_blank\">Download React gantt chart component demo from GitHub<\/a><\/strong><\/p>\n<h4>Conclusion<\/h4>\n<p>Today we have shown you how to add a Gantt chart to the ReactJS app, how to configure the Gantt chart and to process changes made by the user. As you can see, <a href=\"\/\/dhtmlx.com\/docs\/products\/dhtmlxGantt\/\">dhtmlxGantt<\/a> allows doing it quite easily.<\/p>\n<h5>What would you like to see in our next articles about dhtmlxGantt?<\/h5>\n<p>We need your feedback to provide the right integrations at the right time. Please leave your requests in the comment section below.<\/p>\n<p>Thank you in advance and stay tuned for new tutorials!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Updated on February 07, 2022 We won&#8217;t stop till show you that you can use our Gantt chart library with any technology! And today is the turn of ReactJS, &#8230;<\/p>\n","protected":false},"author":2,"featured_media":4069,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[17,71,1,38],"tags":[33,20,14,60,56],"class_list":["post-4066","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-posts-for-codeproject-com","category-tutorials","category-uncategorized","category-visible","tag-all-posts","tag-gantt","tag-tips","tag-integrations-gantt","tag-react"],"_links":{"self":[{"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/posts\/4066","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/comments?post=4066"}],"version-history":[{"count":45,"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/posts\/4066\/revisions"}],"predecessor-version":[{"id":14385,"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/posts\/4066\/revisions\/14385"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/media\/4069"}],"wp:attachment":[{"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/media?parent=4066"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/categories?post=4066"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/dhtmlx.com\/blog\/wp-json\/wp\/v2\/tags?post=4066"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}