Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React document.removeEventListener is not working

I'm trying to make a draggable React component, and the code always manages to reach the 'removing listeners' block, but afterwards the component continues sticking to my mouse, so definitely I've screwed up the removing listeners step, though I'm not sure how--surely the two functions I've passed into document.add/removeEventListener are the same?

useEffect(() => {
            if (dragging && !prevDragging) {
                document.addEventListener("mousemove", onMouseMove)
                document.addEventListener("mouseup", onMouseUp)
            } else if (!dragging && prevDragging) {
                console.log('removing listeners')
                document.removeEventListener("mousemove", onMouseMove)
                document.removeEventListener("mouseup", onMouseUp)
                }
            }
        )

 const onMouseMove = (e) => {
            if (!dragging) return;
            setPos({
                x: e.pageX - rel.x,
                y: e.pageY - rel.y
            });
        e.stopPropagation();
        e.preventDefault();
    }

const onMouseUp = (e) => {
        setDragging(false);
        e.stopPropagation();
        e.preventDefault();
    }
like image 585
shadowstuff Avatar asked Sep 19 '25 17:09

shadowstuff


2 Answers

Just use Reacts useCallback function so React will memorize that the functions are same.

const onMouseMove = React.useCallback((e) => {
  if (!dragging) return;
  setPos({
    x: e.pageX - rel.x,
    y: e.pageY - rel.y,
  });
  e.stopPropagation();
  e.preventDefault();
}, []);

const onMouseUp = React.useCallback((e) => {
  setDragging(false);
  e.stopPropagation();
  e.preventDefault();
}, []);
like image 91
Hydyr Avezberdiyew Avatar answered Sep 22 '25 08:09

Hydyr Avezberdiyew


On each render of React component a new function is created. So if you check in your browser's developer tools for the event listeners you'll see a couple of them added after each render. So even if you remove the latest event listener, the old one's are still there.

So essentially what I am saying is that the function:-

const onMouseMove = (e) => {
            if (!dragging) return;
            setPos({
                x: e.pageX - rel.x,
                y: e.pageY - rel.y
            });
        e.stopPropagation();
        e.preventDefault();
    }

on first render is not same as

const onMouseMove = (e) => {
            if (!dragging) return;
            setPos({
                x: e.pageX - rel.x,
                y: e.pageY - rel.y
            });
        e.stopPropagation();
        e.preventDefault();
    }

on second render and so on. They are logically equivalent but do not refer to the same function.

like image 39
Lakshya Thakur Avatar answered Sep 22 '25 09:09

Lakshya Thakur