I am using antd for create a table in reactJs.
I added eventListener to th tag because I want to be able to drag the columns.
I do it with useRef to get all the th tags:
const [cols, setCols] = useState(columns); // -> columns is static array of object
const tableRef = useRef(null);
useEffect(() => {
if (tableRef.current) {
let elems = tableRef.current.ownerDocument.querySelectorAll('th');
for (let i = 0; i < elems.length; i++) {
elems[i].setAttribute('draggable', true);
elems[i].addEventListener('dragstart', (e) => {
handleDragStart(e);
});
elems[i].addEventListener('dragover', (e) => {
handleDragOver(e);
});
elems[i].addEventListener('drop', (e) => {
handleOnDrop(e);
});
}
}
}, [cols]); // -> cols is the updated columns after change order
const handleDragStart = (e) => {
const { innerText } = e.target;
const idx = cols.findIndex((x) => x.title === innerText);
e.dataTransfer.setData('colIdx', parseInt(idx));
};
const handleDragOver = (e) => {
e.preventDefault();
};
const handleOnDrop = (e) => {
const { innerText } = e.target;
const droppedColIdx = cols.findIndex((x) => x.title === innerText);
const draggedColIdx = parseInt(e.dataTransfer.getData('colIdx'));
setCols(() => {
const tempCols = [...cols];
tempCols.splice(droppedColIdx, 0, tempCols.splice(draggedColIdx, 1)[0]);
return tempCols;
});
};
My problem:
The columns are draggable and I can move them.
If in the useEffect dependency I add cols array, in the first drag the useEffect will call one time, in the second drag the useEffect will call 2 times, in the third drag the useEffect will call 4 times, in the fourth drag the useEffect will call 8 times and so on.
That is every time the useEffect is call, it multiple the call in 2.
If I remove cols array from useEffect dependency, after the first drag everything is ok, but in the second drag my cols reset and initialized to columns.
Thank you for helping me.
>Solution :
You need to remove the listeners in the return of the useEffect in the following manner:
useEffect(() => {
const handleClick = event => {
console.log('Button clicked');
};
const element = ref.current;
element.addEventListener('click', handleClick);
// 👇️ remove the event listener when component unmounts
return () => {
element.removeEventListener('click', handleClick);
};
}, []);