2017-01-19 3 views
3

Я создал HOC для прослушивания кликов вне его завернутого компонента, так что завершенный компонент может прослушивать и реагировать по мере необходимости.Reactjs - Unmount более высокого порядка не работает правильно

Специальный выглядит следующим образом:

const addOutsideClickListener = (WrappedComponent) => { 

    class wrapperComponent extends React.Component { 

     componentDidMount() { 
      console.log('*** component did MOUNT called ***'); 
      document.addEventListener('click', this._handleClickOutside.bind(this), true); 
     } 

     componentWillUnmount() { 
      console.log('*** component will UNMOUNT called ***'); 
      document.removeEventListener('click', this._handleClickOutside.bind(this), true); 
     } 

     _handleClickOutside(e) { 
      const domNode = ReactDOM.findDOMNode(this); 

      if ((!domNode || !domNode.contains(e.target))) { 

       this.wrapped.handleClickOutside(); 
      } 
     } 

     render() { 

      return (
       <WrappedComponent 
        ref={(wrapped) => { this.wrapped = wrapped }} 
        {...this.props} 
       /> 
      ); 
     } 
    } 

    return wrapperComponent; 
} 

Он отлично работает ... большая часть времени.

Когда обернутый компонент демонтирован, метод «componentWillUnmount» вызывается, но «removeEventListener» продолжает прослушивать события, и поэтому я получаю сообщение об ошибке «Uncaught Ошибка: findDOMNode было вызван на отмонтированной компоненте.»

Любые идеи, что может быть причиной этого?

+0

увидеть это: https://gist.github.com/Restuta/e400a555ba24daa396cc, когда вы используете "привязку" а новая функциональная ссылка сделана так технически, что вы пытаетесь удалить другую функцию – Jayce444

+0

спасибо! это изменение создает новую проблему - теперь я получаю эту ошибку при каждом щелчке везде. «Неиспользуемая ошибка: элемент не является ни ReactComponent, ни DOMNode». – Petrov

+0

Я разместил новый вопрос, чтобы правильный ответ здесь получился. Пожалуйста, см. Http://stackoverflow.com/questions/41740360/reactjs-higher-order-component-unmount-not-working-correctly-part-2 – Petrov

ответ

1

Добавьте к этому конструктору:

this._handleClickOutside = this._handleClickOutside.bind(this) 

, а затем сделать это:

componentDidMount() { 
      document.addEventListener('click', this._handleClickOutside, true); 
     } 

     componentWillUnmount() { 
      document.removeEventListener('click', this._handleClickOutside, true); 
     } 
+0

НО это решение теперь выдает ошибку, b/c document.addEventListener связывает обратный вызов с «документом» ... – Petrov

+0

Какая ошибка? это на самом деле другая ошибка, в вашем коде вы не удаляли прослушиватель событий к добавленной функции, вы создавали новую функцию, можете ли вы ввести здесь, что такое ошибка в консоли? – challenger

+0

Проблема в том, что document.addEventListener автоматически привязывает обратный вызов this._handleClickOutside к документу. Поэтому, хотя я привязываюсь к компоненту в конструкторе, внутри обратного вызова, const domNode = ReactDOM.findDOMNode (this); заканчивается тем, что вызывается на «документе» ...это, кажется, известный беспорядок: https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#The_value_of_this_within_the_handler – Petrov

3

Причина, по которой ваш removeEventListener не работает, заключается в том, что вы пытаетесь удалить новую функцию. То же самое относится к addEventListener. Это две полностью разностные функции и не имеют никакой ссылки на друг друга.

Вы должны связать свой метод _handleClickOutside, так что React знает там ровно одну его версию. Вы делаете это путем связывания его в конструкторе с

constructor() { 
    super(); 
    this._handleClickOutside.bind(this); 
} 

или авто связать его с методологией стрелки ES6

_handleClickOutside = (e) => { ... } 

Теперь вы передаете переплетены метод своим eventlisteners с

document.addEventListener('click', this._handleClickOutside, true); 

и соответственно, прослушиватель удаления.

+0

OK попробовал ваше предложение, теперь получаю сообщение «Uncaught Error: Element, похоже, не является ни ReactComponent или DOMNode "при каждом нажатии. – Petrov

+0

Это новый вопрос, который я думаю, поэтому я поставил его здесь: – Petrov

+0

Здесь http://stackoverflow.com/questions/41740360/reactjs-higher-order-component-unmount-not-working-correctly-part-2 – Petrov