Search code examples
javascriptreactjsreact-hooksaddeventlistenerremoveeventlistener

useEffect not showing error for non existent event listener in cleanup


So as per documentation in React, the initial state of the below code of canMove is true. I changed it to false.

import React from "react";
import "./style.css";
import { useState, useEffect } from 'react';

export default function App() {
  const [position, setPosition] = useState({ x: 0, y: 0 });
  const [canMove, setCanMove] = useState(false);

  useEffect(() => {
    function handleMove(e) {
      setPosition({ x: e.clientX, y: e.clientY });
    }
    if (canMove)
      window.addEventListener('pointermove', handleMove);

    return () => window.removeEventListener('pointermove', handleMove);
  }, [canMove]);

  return (
    <>
      <label>
        <input type="checkbox"
          checked={canMove}
          onChange={(e) => {
            setCanMove(e.target.checked)
            }
          } 
        />
        The dot is allowed to move
      </label>
      <hr />
      <div style={{
        position: 'absolute',
        backgroundColor: 'pink',
        borderRadius: '50%',
        opacity: 0.6,
        transform: `translate(${position.x}px, ${position.y}px)`,
        pointerEvents: 'none',
        left: -20,
        top: -20,
        width: 40,
        height: 40,
      }} />
    </>
  );
}

So after first render, useEffect runs but adding event listener to "pointermove" is dependent on canMove which is now false and hence no event listener is added. Now if we click the checkbox, canMove is true this triggers the useEffect again, and the cleanup should run first. But there is no handlemove function added to pointer move previously. So this line should give error logically?


Solution

  • It's not an error to enqueue removal of an event listener... if it exists then it will be removed, otherwise, it's ignored. See EventTarget: removeEventListener:

    Calling removeEventListener() with arguments that do not identify any currently registered event listener on the EventTarget has no effect.

    This means your current/initial code is ok, no error should be thrown because an event listener wasn't added previously.