Страницы

Поиск по вопросам

понедельник, 18 марта 2019 г.

stopPropagation для отмены изменения state в React

Есть функция, которая меняет состояние state, срабатывающая при клике на внутреннем элементе:
toggleModal(typeModal){ this.setState({ [typeModal]: !this.state[typeModal] }); }
При клике вне элемента состояние state должно изменяться:
closeModal(typeModal){ this.setState({ [typeModal]: false }); }
closeModal вещаем на onClick у контейнера, например, Body.
Вопрос: как запретить всплытие изменения состояния на элементе? (return false; и event.stopPropagation() не работают)


Ответ

1. Информация в вопросе слегка неполна и противоречива. Начнем, с того что согласно документации event.stopPropagation лучше применять с версии 0.14, до нее можно возвращать false у обработчика. И если Вы обрабатываете все с помощью реактовской системы событий, все должно работать.
2. Proof of concept: jsfiddle. Только с реактовскими событиями, обработчик клика висит на контейнере.
3. Значит остается достать хрустальный шар и угадать что не работает у вас. Вероятнее всего Вы мешаете реактовские события с браузерными.
closeModal вещаем на onClick у контейнера, например, Body.
Т.е. body это у вас не ректовский компонент а самое что ни на есть document.body с событием onclick. React использует свою систему синтетических событий. Физически, по крайней мере для всплывающих событий это один обработчик на document, дальше используется делегирование. Поэтому такой подход напрямую не сработает: к моменту когда событие до реактовского обработчика дойдет, оно уже всплыло.
4. Окей, как тогда мне ловить клик снаружи компонента? Можно сделать например так: jsfiddle. Смысл в том что пока компонент существует, на document висит наш обработчик клика. Срабатывание его при клике на сам компонент мы обрабатываем ручками в самом обработчике. Если у вас устаревшая версия реакта, (<0.14), то апи может быть чуть чуть другим, но смысл от же.
Магия происходит здесь:
// Привязываем-отвязываем обработчик на документ, соответственно жизненному циклу компонента componentWillMount: function () { document.addEventListener('click', this.unStrike, false); },
componentWillUnmount: function () { document.removeEventListener('click', this.unStrike, false); },
и здесь:
unStrike: function(event){ // предотвращаем срабатывание на самом элементе if (ReactDOM.findDOMNode(this).contains(event.target)) { return; } // smth else },

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

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