afterChange causing performance issues

Tags: #<Tag:0x00007f0b039e7630>

Not sure if this is my implementation (or if the new react version where “on” is dropped from the function would fix this), but when I added onAfterChange, tabbing and using arrow navigation through the cells is much slower. Here are my settings:

    this.id = 'hot';
    this.hotSettings = {
      data: this.state.grid,
      renderer: 'html',
      stretchH: 'all',
      manualRowResize: true,
      manualColumnResize: true,
      colHeaders: true,
      rowHeaders: true,
      colWidths: this.state.colWidths,
      rowHeights: 30,
      minCols: 26,
      minRows: 100,
      contextMenu: true,
      formulas: true,
      columnSorting: true,
      autoRowSize: true,
      manualColumnMove: true,
      manualRowMove: true,
      ref: "hot",
      fixedRowsTop: 0,
      minSpareRows: 1,
      comments: true,
      licenseKey: myKey,
      onAfterChange: (changes, source) => {if(changes){
        clearTimeout(this.timeout);
        this.timeout = setTimeout(this.handleAddItem, 3000)
      }},
      onAfterSelection: (r, c, r2, c2, preventScrolling) => {
         preventScrolling.value = true;
         this.captureCellData([r, c]);
       },
       onAfterColumnResize: (currentColumn, newSize, isDoubleClick) => {
         this.handleResizeColumn([currentColumn, newSize]);
         setTimeout(this.handleAddItem, 3000)
       }
    };
    this.hotTableComponent = React.createRef();```

Any thoughts or is this a known performance issue tied to using afterChange?

Hi @justin1

Can you create s Stackblitz demo? It would be much easier to debug

Thanks for the response @aleksandra_budnik! Here’s the stackblitz I created:

https://react-9jdxku.stackblitz.io

Editor: https://stackblitz.com/edit/react-9jdxku

Once you start entering content, the performance is slowed down considerably. It seems to be tied to the function I’m running when afterChange is fired.

Thank you for sharing the demo.

I see that the selection itself is little bit laggy. I am using Chrome 69/Windows 10.

I will test it more.

The slowness of the selection and editor is caused by afterSelection callback logic (line 51-54)

afterSelection: (r, c, r2, c2, preventScrolling) => {
         preventScrolling.value = true;
         this.captureCellData([r, c]);
       },

Thanks, Aleksandra. Can you elaborate a little? What’s wrong with the logic? I’m calling a function that sets state for use later if the user wants to, say, format the cell.

line 53 the captureCellData logic takes a lot of calls and it becomes really heavy for Handsontable.
Can you tell me what captureCellData suppose to do? I see the code but want to know your requirements. Maybe we’ll be able to restrict some unnecessary calls.

Sure! captureCellData does a few things:

  1. Sets a boolean indicator to tell me whether a row range has been selected
  2. Sets a boolean indicator to tell me whether a col range has been selected
  3. Stores the data location (row, col) in state (as you see in the example, I’m using React)
  4. Stores the actual content of the cell in state
  5. Sets the range parameters of the selection (from row, to row, from col, to col)

The above is what that function does. Everything I outline below happens outside of that function but refers to the data captured in that function.

I have a formatting bar that allows users to set the color of selected cell data (or they can make it bold or italicized). When they click that button, I am checking to see what cell has been selected and if more than one cell has been selected. If it’s a single cell, I just set the formatting on that cell data. If it’s a range of cells, I look through the range and set the formatting of each cell in the range.

I also have an input text field (like you see in Excel and Google Sheets. To get that input’s value property to match the selected cell, I’m using the state I set in the captureCellData function.

Obviously, not all of this was captured in the example code because it’s a lot, but if you need examples, I can provide them. I’m eager to know if there is a better way to do this, but I can’t think of one.

I think I have a solution. I’m using the same logic I used in the afterChange event with setTimeout and clearTimeout. That has drastically improved performance.

Here’s the updated code:

         preventScrolling.value = true;
         clearTimeout(this.timeout);
         this.timeout = setTimeout(() => this.captureCellData([r,c]), 500);
       },```

Thanks for your help!

That is great! I just read the post - sorry for keeping you waiting.

Does it works the same after this 5 days?

Yep, it’s working great. Thanks!

Great. Thank you for confirmation.

I guess that we can close the topic.