Search code examples
javascriptreactjsthisarrow-functions

Why the arrow function that returns arrow function inside componentWillUnmount lifecycle is not removed by removeEventListener? (React.js)


I am currently working on React.js Class component.

I have added listener using addEventListener inside componentDidMount like below.

  componentDidMount() {
    document.addEventListener('copy', this.copyBlock('copy'));
    document.addEventListener('cut', this.copyBlock('cut'));
  }


  componentWillUnmount() {
    document.removeEventListener('copy', this.copyBlock('copy'));
    document.removeEventListener('cut', this.copyBlock('cut'));
  }

  // This is the function that added by addEventListener.
  // As you can see, argument copyType is passed to copyBlock function and returns event object.
  copyBlock = (copyType: 'copy' | 'cut') => (e: ClipboardEvent) => {
    if (e.target !== document.body) {
      return;
    }
    const {
      type,
      libraryStore: { showUtilBlock },
    } = this.props;

    BlockUtil.copyBlock(e, copyType);
  };

However, here is the problem.

When the component is unmounted, the function is supposed to be removed. However, it is not.

But, When I changed copyBlock function like below, it works. it is removed.

  componentDidMount() {
    document.addEventListener('copy', this.copyBlock);
  }


  componentWillUnmount() {
    document.removeEventListener('copy', this.copyBlock);
  }

  copyBlock = (e?: ClipboardEvent) => {
    if (e.target !== document.body) {
      return;
    }
    const {
      type,
      libraryStore: { showUtilBlock },
    } = this.props;

   BlockUtil.copyBlock(e, 'copy');
  };

What is the difference? Why eventListener does not work on the arrow function that returns function?


Solution

  • Because it will create a new event handler every time when you call this.copyBlock(). Each of them has a different pointer. The event handler that passed in removeEventListener() should be the same as the event handler passed in addEventListener().(Same pointer)

    Try this:

    constructor() {
      this.copy = this.copyBlock('copy');
      this.cut = this.copyBlock('cut');
    }
    
    componentDidMount() {
      document.addEventListener('copy', this.copy);
      document.addEventListener('cut', this.cut);
    }
    
    componentWillUnmount() {
      document.removeEventListener('copy', this.copy);
      document.removeEventListener('cut', this.cut);
    }