I'm trying to use event.stopPropagation() within a ReactJS component to stop a click event from bubbling up and triggering a click event that was attached with JQuery in legacy code, but it seems like React's stopPropagation() only stops propagation to events also attached in React, and JQuery's stopPropagation() doesn't stop propagation to events attached with React.
Is there any way to make stopPropagation() work across these events? I wrote a simple JSFiddle to demonstrate these behaviors:
/** @jsx React.DOM */
var Propagation = React.createClass({
alert: function(){
alert('React Alert');
},
stopPropagation: function(e){
e.stopPropagation();
},
render: function(){
return (
<div>
<div onClick={this.alert}>
<a href="#" onClick={this.stopPropagation}>React Stop Propagation on React Event</a>
</div>
<div className="alert">
<a href="#" onClick={this.stopPropagation}>React Stop Propagation on JQuery Event</a>
</div>
<div onClick={this.alert}>
<a href="#" className="stop-propagation">JQuery Stop Propagation on React Event</a>
</div>
<div className="alert">
<a href="#" className="stop-propagation">JQuery Stop Propagation on JQuery Event</a>
</div>
</div>
);
}
});
React.renderComponent(<Propagation />, document.body);
$(function(){
$(document).on('click', '.alert', function(e){
alert('Jquery Alert');
});
$(document).on('click', '.stop-propagation', function(e){
e.stopPropagation();
});
});
This question is related to
javascript
jquery
reactjs
Update: You can now <Elem onClick={ proxy => proxy.stopPropagation() } />
React 17 delegates events to root
instead of document
, which might solve the problem.
More details here.
Worth noting (from this issue) that if you're attaching events to document
, e.stopPropagation()
isn't going to help. As a workaround, you can use window.addEventListener()
instead of document.addEventListener
, then event.stopPropagation()
will stop event from propagating to the window.
A quick workaround is using window.addEventListener
instead of document.addEventListener
.
I was able to resolve this by adding the following to my component:
componentDidMount() {
ReactDOM.findDOMNode(this).addEventListener('click', (event) => {
event.stopPropagation();
}, false);
}
From the React documentation: The event handlers below are triggered by an event in the bubbling phase. To register an event handler for the capture phase, append Capture. (emphasis added)
If you have a click event listener in your React code and you don't want it to bubble up, I think what you want to do is use onClickCapture
instead of onClick
. Then you would pass the event to the handler and do event.nativeEvent.stopPropagation()
to keep the native event from bubbling up to a vanilla JS event listener (or anything that's not react).
I ran into this problem yesterday, so I created a React-friendly solution.
Check out react-native-listener. It's working very well so far. Feedback appreciated.
It is still one intersting moment:
ev.preventDefault()
ev.stopPropagation();
ev.nativeEvent.stopImmediatePropagation();
Use this construction, if your function is wrapped by tag
Source: Stackoverflow.com