почему эта реакция/javascript removeEventListener не удаляет слушателя?

Похоже, слушатели здесь не удаляются. Есть идеи, как это исправить? Я предполагаю, что это связано с тем, как я «делюсь» слушателем, и я использую функции стрелок (согласно рекомендации здесь https://medium.freecodecamp.org/reactjs-pass-parameters-to-обработчикисобытий-ca1f5c422b9)

Код:

import * as React from 'react';

export default class ITestComponent extends React.Component { 

  public render() {
    return (
      <div>

        <div 
          onMouseDown={this.handleMouseDown('horizontal')}
          draggable={false}
          style={{ border: '1px solid blue', padding:20 }}
        >
          Horizontal Drag Test
        </div>

        <div 
          onMouseDown={this.handleMouseDown('vertical')}
          draggable={false}
          style={{ border: '1px solid green', padding:20 }}
        >
          Vertical Drag Test
        </div>

      </div>
    );
  }

  private handleMouseDown = (eType:string) => (e:any) => {
    console.log('Add Event Listeners (handleMouseDown)', eType)
    window.addEventListener('mousemove', this.handleMouseMove(eType))
    window.addEventListener('mouseup', this.handleMouseUp(eType))
  }

  private handleMouseMove = (eType:string) => (e:MouseEvent) => {
    console.log(' - handleMouseMove', eType, e.clientY)
  };

  private handleMouseUp = (eType:string) => (e:MouseEvent) => {
    console.log('Remove Listeners (handleMouseUp)', eType)
    window.removeEventListener('mousemove', this.handleMouseMove(eType))
    window.removeEventListener('mouseup', this.handleMouseUp(eType));
  };

}

Вывод консоли после нажатия на «тест горизонтального перетаскивания» и перетаскивания вниз (с нажатой кнопкой мыши), отпускания кнопки мыши, затем перетаскивания еще немного..

Add Event Listeners (handleMouseDown) horizontal
 - handleMouseMove horizontal 61
 ...
 - handleMouseMove horizontal 220
 - handleMouseMove horizontal 221
Remove Listeners (handleMouseUp) horizontal
 - handleMouseMove horizontal 222
 - handleMouseMove horizontal 222
 - handleMouseMove horizontal 228
 ...

В частности, вопрос заключается в том, как сохранить концепцию «повторного использования» обработчика событий для нескольких целей?

Обратите внимание, что я не использую здесь анонимную функцию, как в одном из предложенных ответов (Javascript removeEventListener не работает)


comment
this.handleMouseMove(eType) возвращает новую функцию каждый раз, когда вы ее используете, поэтому ссылка на удаляемую функцию не совпадает с той, которую вы добавляете.   -  person Tholle    schedule 21.12.2018
comment
Возможный дубликат Javascript removeEventListener не работает   -  person Patrick Hund    schedule 21.12.2018
comment
но я предполагаю, что задан вопрос, я хочу иметь возможность передать параметр (чтобы поделиться обработчиком события), тогда как это возможно сделать, т.е. нужен способ удалить обработчик?   -  person Greg    schedule 21.12.2018


Ответы (1)


Даже когда вы определяете свою функцию с каррированными стрелочными функциями и выполняете, скажем, this.handleMouseDown('horizontal'), каждый раз возвращается новый экземпляр функции, и для того, чтобы назначать и удалять прослушиватели событий, необходимо передать один и тот же экземпляр функции. Вы можете реализовать вышеизложенное следующим образом

import * as React from 'react';

export default class ITestComponent extends React.Component { 

  public render() {
    return (
      <div>

        <div 
          onMouseDown={this.handleMouseDown.bind(this,'horizontal')}
          draggable={false}
          style={{ border: '1px solid blue', padding:20 }}
        >
          Horizontal Drag Test
        </div>

        <div 
          onMouseDown={this.handleMouseDown.bind(this,'vertical')}
          draggable={false}
          style={{ border: '1px solid green', padding:20 }}
        >
          Vertical Drag Test
        </div>

      </div>
    );
  }

  private handleMouseDown = (eType:string, e:any) => {
    console.log('Add Event Listeners (handleMouseDown)', eType)
    this._handleMouseMove = this.handleMouseMove.bind(this, eType);
    this._handleMouseUp = this.handleMouseUp.bind(this, eType);
    window.addEventListener('mousemove', this._handleMouseMove)
    window.addEventListener('mouseup', this._handleMouseUp)
  }

  private handleMouseMove =  (eType: string, e:MouseEvent) => {
    console.log(' - handleMouseMove', eType, e.clientY)
  };

  private handleMouseUp = (eType:string, e:MouseEvent) => {
    console.log('Remove Listeners (handleMouseUp)', eType)
    window.removeEventListener('mousemove', this._handleMouseMove)
    window.removeEventListener('mouseup', this._handleMouseUp);
  };

}

person Shubham Khatri    schedule 21.12.2018
comment
спасибо, Шубхам - так что, действительно, нет способа избежать использования привязки здесь? т.е. не может решить, используя стрелочные функции в этом случае? - person Greg; 21.12.2018
comment
Вы можете избежать привязки в рендере, создав компонент из элемента, но не в слушателях. См. stackoverflow.com/questions/45053622/ - person Shubham Khatri; 21.12.2018