Gantt not re-rendering after update

Hi there,

I am using react JS here, so I basically set the Dhtmlx component in my project like is showing in this example:
dhtmlx.com/blog/create-react-ga … tmlxgantt/

I am not going to use the lightbox that the component uses to add and edit tasks. Instead, I created this modal that the user can open that is located on the same page the component is being rendered. Therefore, it’s basically my way to add tasks to my database without using the lightbox.
Why is that? I need to keep the layout of my application.

That is working to add new tasks just fine, and I am able to load the tasks in the component with all the correct values. In order to load the tasks, I use an Axios call to deliver the JSON to the data property.

The component is not re-rendering after adding a new task and closing the modal though.

In the example providaded there is a call to the function “shouldComponentUpdate” like the one bellow.

shouldComponentUpdate(nextProps){
return this.props.tasks.data.length !== nextProps.tasks.data.length
//return this.props.zoom !== nextProps.zoom
}

I am pretty sure that after creating my new task and closing the modal, that function is called and the properties “lenght” are different. Shouldn’t that be enough to re-render the component?

I am also pretty sure that my variable “data” that carries the JSON to deliver to the component was updated by axios.

Hi,

Could you please provide with access to your application or create any demo?
Unfortunately it’s not obvious what is the cause of the issue.

Hi Polina,

I won’t be able to provide an demo, neither give access to the application because I haven’t published it in the cloud yet.
However, I can show you my code, which is basically like the example provided in the website.

The difference is how I am delivering data to the component. I attached here the two JSX files I have been working on. I hope you don’t find my code a mess :frowning: , I am a beginner, so I’m sorry if I making my problem difficult to understand.

In the file “gantt-app.jsx” I have this function named “atualizar()” that will use Axios to get tasks from my Controller and set the result to a state variable called “this.state.acoes”.

  atualizar(){
    this.setState({
      'isLoading': true
    })
    if (!this.props.id) {
      axios.post(`/Acao/ObterAcoesPorItem`, {
        itemId : this.props.itemId,
        parameters: this.props.parameters

      }).then((response) => {
        this.setState({
          loaded: true,
          isLoading: false,
          acoes:response.data
        })
      })
    }
  }[/code]


 In the "render()" method I map that state variable in a new variable with the format that Gantt component requires.

[code]    let acoes = this.state.acoes && this.state.acoes.map((acao) => (
      {
        id: acao.id,
        text: acao.descricao,
        codigo:acao.codigo,
        start_date: acao.dataInicioPrevista,
        farol_acao:acao.farolAcao,
        duration: this.handleDuration(acao.dataInicioPrevista,acao.dataFimPrevista),
        progress: this.handleProgress(acao.percentualRealizado),
        percentual_previsto:this.handlePercentualPrevisto(
          this.handleDuration(acao.dataInicioPrevista,acao.dataFimPrevista),
          acao.dataInicioPrevista
        ),
        holder:acao.responsavel.nome,
        status_acao:acao.status.descricao,
        baseline_inicial:this.handleValorNulo(acao.baselineInicial),
        baseline_final:this.handleValorNulo(acao.baselineFinal),
        data_inicio_realizada:this.handleValorNulo(acao.dataInicioRealizada),
        data_fim_realizada:this.handleValorNulo(acao.dataFimRealizada),
        observacao:this.handleValorNulo(acao.observacao),
        como:this.handleValorNulo(acao.como),
        onde:this.handleValorNulo(acao.onde),
        porque:this.handleValorNulo(acao.porque)

      }
    ))

    let data = {
      data:[].concat(acoes)
    }[/code]

 Then, I return a div with the component

[code]return(
      <div>
      <Panel style={{marginTop: 15, height: 700}}>
            <Content  {...this.props}>

              <Row>
                <div className="gantt-container">
                  {
                   acoes &&
                    <Gantt
                      tasks={data}
                      zoom={this.state.currentZoom}
                      onTaskUpdated={this.handleTaskUpdate}
                      onLinkUpdated={this.logLinkUpdate}
                    />
                  }
                </div>
              </Row>
              <MessageArea
                messages={this.state.messages}
              />
            </Content>
      </Panel>
    </div>
    )[/code]


This is working fine. However, I use a modal to create a new Task. I am not using the lightbox the component provides. Right after creating a new task I call this method "handleClose" that will update my state variable "this.state.acoes" again:
[code]  handleCloseAcao(){
    this.atualizar()
  }

Now… Here is where the problem happens. Right after calling that method, my state variable got updated, but the component is not rendering the new data it is receiving.

I attached here a print screen showing that the gantt component is receiving props and the method “shouldcomponentUpdate” is returnig true.



gant.zip (3.77 KB)

arthurmmedeiros: did you end up getting this working? I’m also trying to integrate react.js with gantt and am finding that when I change the scale and other such settings, it’s not enough for me to just gantt.render(), I need to reload all my tasks for it to work, which seems wasteful:

This doesn’t work when prevProps.scale is changed and I change gantt.config.scale_unit = ‘week’;

	componentDidUpdate(prevProps) {
		if (prevProps.items !== this.props.items) {
			gantt.clearAll();
			gantt.parse({ 
				data: this.props.items
			});	
		}
		
		gantt.render();		
	}

But this does work when prevProps.scale is changed and I change gantt.config.scale_unit = ‘week’;

	componentDidUpdate(prevProps) {
		gantt.clearAll();
		gantt.parse({ 
			data: this.props.items
		});	
		
		gantt.render();		
	}

Nevermind. It was a bug on my end. Darn javascript/react and lack of typing. :slight_smile:

What went wrong in your case, @leojhartiv ?

I’m facing similar problem using Angular.

Hello Marcin,
Please, describe what actually happens in your case and send me a demo project so that I can reproduce the issue locally and check what might be wrong.

arthurmmedeiros: Were you able to re-render the component when props changes.

I am working with dhtmlx-scheduler and React. My application is as follows:

From react-select, when I select a value, dhtmlx-scheduler shows the correct values. But when I deselect the value , then scheduler does not update.

Any help would be appreciated.
Thanks

Hello, If you are passing the tasks as props , i suggest you just do as folow in you Gantt.js

componentWillReceiveProps() {

    const { tasks } = this.props;

    gantt.parse(tasks);

  }

I have sample problems related with this case. addTaskLayer but It not re-render layers
https://docs.dhtmlx.com/gantt/api__gantt_addtasklayer.html#smartrenderingforcustomlayers

%E1%BA%A3nh
My code
%E1%BA%A3nh

Hello @doumar,

Just for sure: the addTaskLayer is available only in the “PRO” versions of gantt and isn’t available in “GPL”. You can check your version by printing the gantt.version command in the browser console.

Regarding the question:

It looks like you copied the “pseudocode” from the documentation, and the issue comes exactly from the getRectangle method, as you are trying to return the following coordinates object: {left, top, height, width}, when it’s parameters(left, top, height, width) are not defined. Usually you can get the coordinates using the getTaskPosition method:
https://docs.dhtmlx.com/gantt/api__gantt_gettaskposition.html

Here is the demo with corrected code, which works correctly:
http://snippet.dhtmlx.com/5/a969ae9bc

You can find the real code example little bit below in the same thread:

gantt.addTaskLayer({
    renderer: {
      render: function draw_planned(task) {
        if (task.planned_start && task.planned_end) {
          var sizes = gantt.getTaskPosition(task,task.planned_start,task.planned_end);
          var el = document.createElement('div');
          el.className = 'baseline';
          el.style.left = sizes.left + 'px';
          el.style.width = sizes.width + 'px';
          el.style.top = sizes.top + gantt.config.task_height + 13 + 'px';
          return el;
        }
        return false;
      },
      // define getRectangle in order to hook layer with the smart rendering
      getRectangle: function(task, view){
        return gantt.getTaskPosition(task, task.planned_start, task.planned_end);
      }
    }
});

Here is the sample used as a code reference for this thread:
https://docs.dhtmlx.com/gantt/samples/04_customization/14_deadline.html
You find the full code of this example in the package(PRO) you downloaded, by the following address: downloaded_package/samples/04_customization/14_deadline.html

If it didn’t help you, could you please reproduce the issue in the following snippet(reproduce the issue => click the “Share” button => send me the new link):
https://snippet.dhtmlx.com/5/98dc2fab0

1 Like

It seem I got problem with version
my current version : 6.1.7. Does it include this feature

Hello @doumar,

Thank you for the clarification, It’s really a version issue. The “renderer” method was added in the 6.3 version, in order to connect the “addTaskLayer” with smart render functionality.

In the 6.1.7 version you can use the following syntax:

gantt.addTaskLayer(function customRender(task){

  var main_div = document.createElement("div");
  main_div.classList.add("red-rect")
  var sizes = gantt.getTaskPosition(task, task.start_date);

  main_div.style.left = sizes.left + 'px';
  main_div.style.top = sizes.top + 'px';
  return main_div;


});

Here is the updated demo:
http://snippet.dhtmlx.com/5/5d2443201

You can also find the actual to your version code example in your package by the following address:
downloaded_package/samples/04_customization/14_deadline.html