i am using version 14
i have a state in react
const [cellMeta, setCellMeta] = useState([]);
on afterSetCellMeta i call a function to insert the meta for the cells and i pass the state to handsontable cell
cell={
rows.length && columns.length
? cellMeta
: undefined
}
on doing so an infinte loop starts and i am not able to get the reason why,
Hi @guneetsinghtuli
Thank you for contacting us. Can you please share a code demo where the issue is replicable? It will be easier to debug it this way.
Hey @adrian.szymanski
You can find the code sandbox here https://codesandbox.io/p/devbox/p32xrg
I have added a comment on line 95
In order to replicate
- Open Console
- Click on any header and align it to any direction
- You will find a infinite loop which will eventually crash the application
- You can comment the line 95
cell={cellMeta}
and perform the same in order to see the expected behaviour (it should trigger the function update the state and cell should acknowledge the updated state)
and Please let me know if I am missing on something with this
Hi @guneetsinghtuli
Thank you for the example. I checked it and followed your instructions but I don’t get any errors and sorting works fine. Can you please recheck it?
@guneetsinghtuli
Thank you for the recording. Now I am able to reproduce the issue. I think the reason for the error is explained quite well in the message itself:
Maximum update depth exceeded. This can happen when a component calls setState inside useEffect, but useEffect either doesn’t have a dependency array, or one of the dependencies changes on every render.
So, basically, there are too many updates within the logic you created and the results in an infinite loop.
Hey @adrian.szymanski
Currently in the code base I am only using useEffect to log the updates I can replicate the issue by removing that as well
So I am not sure if it’s the problem with my code logic or an actual issue with handsontable
useEffect(() => {
console.log("cellMeta", cellMeta);
}, [cellMeta]);
@guneetsinghtuli
Maybe let’s change the approach here. Can you please tell me what is your expected result with the logic you have?
@adrian.szymanski
We have a case where the alignment or any css changes to any cell must persist but in order to persist we don’t use any local storage or session since for now we are using a react state
You can just assume it as a normal react state which will persist on reload, So whenever we make any changes to the alignment or any cell level change mostly css.
I saved the changes in a state and then pass it back to the handsontable so on reload as well you fill find the same alignment and css
I can’t use the default handsontable persistence state as I am in a restricted environment of iframe without access to local storage or any other
Hi @guneetsinghtuli
Thank you for the explanation. I did some more research and the reason for the loop is most likely due the fact that you are reading from the state in both cell
option and afterSetCellData
hook. Both of them will trigger re-rendering of the whole table and that will cause the infinite loop. In this case I would suggest to keep the logic and reading from state only to one of those methods.
Hey @adrian.szymanski
I do agree that can a possible explanation for infinite while loop, For My use case In order to save the UI change which user made like alignment or something I can apply the afterSetCellData
hook and save it, But how can I apply the styling back later on after a reload if I can’t use the cell
option is there any other parameter which I can use to pass back the last state of styling ?
@guneetsinghtuli
I’ll check the available options and update you after the weekend.
The reason you are encountering an infinite loop is because you are attempting to set the cell meta in the afterSetCellData
hook. Unfortunately, I couldn’t get setState to work in useEffect. The only way I could get it to work was using a plain JS Map. Does this work for you:
https://codesandbox.io/p/devbox/handsontable-forked-9z845z
Hi @timeflys54321
Thank you for the suggestion. Let’s wait for @guneetsinghtuli confirmation if that helps.
Hey @adrian.szymanski @timeflys54321
Thank you for this suggestion I will try to implement it on my use case and let you know by tomorrow.
Hi @guneetsinghtuli
Is this subject can be closed? If you’d need anything more that what was suggested please let us know.
Hi, I am Dhairya, I work with Guneet.
This is the same code as the solution you posted: https://codesandbox.io/p/devbox/handsontable-forked-9z845z.
The only change I made is adding a log inside afterSetCellMeta to track updates to cellMeta. However, I noticed that when I log the Map, it still shows the previous state instead of reflecting the latest update.
Here’s my implementation:
const cellMeta: Map<
string,
{
row: number;
col: number;
[key: string]: any;
}
> = new Map();
const afterSetCellMeta = (row, col, key, value) => {
const mapKey = `${row},${col}`;
const metaRow = cellMeta.get(mapKey);
if (metaRow) {
cellMeta.set(mapKey, { [key]: value, ...metaRow });
} else {
cellMeta.set(mapKey, { row, col, [key]: value });
}
console.log("Updated cell meta:", cellMeta);
};
code sanbox link of my implementation: https://codesandbox.io/p/devbox/handsontable-forked-mqjjpg?file=%2Fapp%2Fpage.tsx%3A30%2C36
The issue is that cellMeta doesn’t reflect the latest state when logged inside afterSetCellMeta. Instead, it always shows the previous state. It seems like the Map isn’t updating immediately.
Can you suggest a way to get the updated state correctly?
Below is the screen shot to help you identify the issue better.
Hi @dhairyasehgal2307
Thank you for sharing the demo. It uses no theme
. Meaning all elements like arrows (for sorting, dropdown or date), checkboxes, cell classes are not applied. I recommend using Classic
theme (the one that was used before v15.0.0 or any of our new themes Main
or Horizon
. Plus CodeSandbox itself has sometimes issue with integrating Handsontable modules. We used it before but now we moved to Stackblitz. Could you please check what is missing in this demo https://stackblitz.com/edit/react-g3xcx4uf-aa6tkdae?file=src%2FExampleComponent.jsx,src%2Fdata.js?
@dhairyasehgal2307, I made a mistake with the order when constructing the meta object.
It should be:
cellMeta.set(mapKey, { ...metaRow, [key]: value });
instead of
cellMeta.set(mapKey, { [key]: value, ...metaRow });
I’ve updated the fork to reflect that.