score:187

Accepted answer

React uses event delegation with a single event listener on document for events that bubble, like 'click' in this example, which means stopping propagation is not possible; the real event has already propagated by the time you interact with it in React. stopPropagation on React's synthetic event is possible because React handles propagation of synthetic events internally.

Working JSFiddle with the fixes from below.

React Stop Propagation on jQuery Event

Use Event.stopImmediatePropagation to prevent your other (jQuery in this case) listeners on the root from being called. It is supported in IE9+ and modern browsers.

stopPropagation: function(e){
    e.stopPropagation();
    e.nativeEvent.stopImmediatePropagation();
},
  • Caveat: Listeners are called in the order in which they are bound. React must be initialized before other code (jQuery here) for this to work.

jQuery Stop Propagation on React Event

Your jQuery code uses event delegation as well, which means calling stopPropagation in the handler is not stopping anything; the event has already propagated to document, and React's listener will be triggered.

// Listener bound to `document`, event delegation
$(document).on('click', '.stop-propagation', function(e){
    e.stopPropagation();
});

To prevent propagation beyond the element, the listener must be bound to the element itself:

// Listener bound to `.stop-propagation`, no delegation
$('.stop-propagation').on('click', function(e){
    e.stopPropagation();
});

Edit (2016/01/14): Clarified that delegation is necessarily only used for events that bubble. For more details on event handling, React's source has descriptive comments: ReactBrowserEventEmitter.js.

score:3

Update: You can now <Elem onClick={ proxy => proxy.stopPropagation() } />

score:3

A quick workaround is using window.addEventListener instead of document.addEventListener.

score:4

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.

score:6

React 17 delegates events to root instead of document, which might solve the problem. More details here. You can also refer to my blog.

score:7

I was able to resolve this by adding the following to my component:

componentDidMount() {
  ReactDOM.findDOMNode(this).addEventListener('click', (event) => {
    event.stopPropagation();
  }, false);
}

score:11

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).

score:20

It is still one intersting moment:

ev.preventDefault()
ev.stopPropagation();
ev.nativeEvent.stopImmediatePropagation();

Use this construction, if your function is wrapped by tag

score:20

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.


Related Query

More Query from same tag