понедельник, 24 октября 2016 г.

Как заставить работать event.stopPropagation в React, если у document есть свои события

Если требуется, чтобы клик по элементу, созданному с помощью React не доходил до уровня document, на который могут быть навешаны свои события, то для этого надо при создании данного элемента отказаться от добавления событий стандартным способом вроде
<Element onClick={this.handleClick.bind(this)} />, а вместо этого добавить слушатель события внутри функции componentDidMount () {}.

Для примера.

Document имеет свой слушатель события click:

document.addEventListener('click', function () {alert('Событие клика дошло до уровня document');});

Элемент имеет свой слушатель события click:

import React, {Component} from 'react';
import ReactDOM from 'react-dom';

class Element extends Component {
  handleClick (event) {
      event.stopPropagation();
      alert('Вы кликнули по элементу.');
  }
  render () {
      return <div onClick={this.handleClick.bind(this)}>Кликни по мне</div>;
  }
}

ReactDOM.render(<Element />, document.getElementById('root'));

Если в таком виде кликнуть по надписи "Кликни по мне", то сработает событие клика по элементу и событие клика по document, что приведет к выводу на экран двух сообщений alert.

Чтобы заблокировать распространения события необходимо добавление клика на элемент перенести в функцию componentDidMount:

class Element extends Component {
  handleClick (event) {
      event.stopPropagation();
      alert('Вы кликнули по элементу.');
  }
  componentDidMount () {
      ReactDOM.findDOMNode(this.refs.btn).addEventListener('click', this.handleClick);
  }
  render () {
      return <div ref="btn">Кликни по мне</div>;
  }
}

Теперь, если кликнуть по надписи "Кликни по мне", то сработает событие клика только по самому элементу, и событие клика по document, не сработате, что приведет к выводу на экран только одного сообщения alert.

Не забудьте удалить событие клика по элементу, если будет удалять сам компонент:

  componentWillUnmount () {
      ReactDOM.findDOMNode(this.refs.btn).removeEventListener('click', this.handleClick);
  }

Полный вариант кода примера:

import React, {Component} from 'react';
import ReactDOM from 'react-dom';

document.addEventListener('click', function () {alert('Событие клика дошло до уровня document');});

class Element extends Component {
  handleClick (event) {
      event.stopPropagation();
      alert('Вы кликнули по элементу.');
  }
  componentDidMount () {
      ReactDOM.findDOMNode(this.refs.btn).addEventListener('click', this.handleClick);
  }
  componentWillUnmount () {
      ReactDOM.findDOMNode(this.refs.btn).removeEventListener('click', this.handleClick);
  }
  render () {
      return <div ref="btn">Кликни по мне</div>;
  }
}

ReactDOM.render(<Element />, document.getElementById('root'));

Комментариев нет:

Отправить комментарий