react: stopImmediatePropagation is not available for synthetic events

In order to call this method, you’d have to access it via event.nativeEvent.stopImmediatePropagation(): https://developer.mozilla.org/en-US/docs/Web/API/Event/stopImmediatePropagation

It’d be awesome if this was supported on event itself. I did see a prior issue for this, but it was for a use case that sIP wasn’t required for.

For a specific use case: if you want to kill hover events for touch input, onTouchStart will trigger onMouseOver and stopImmediatePropagation cancels that internal cascade.

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Reactions: 21
  • Comments: 15 (1 by maintainers)

Most upvoted comments

I concur with the above. The documentation for SyntheticEvent states:

It has the same interface as the browser’s native event, including stopPropagation() and preventDefault(), except the events work identically across all browsers.

Not having stopImmediatePropagation on it violates the promise that the interface is the same.

If this won’t be fixed, at least fix the docs to stop claiming that the interface is the same when it’s not.

Please, correct me if I’m wrong, but it seems that the biggest problem here is that native events aren’t actually attached to the individual elements, but rather to the root document. You can see this by comparing event.currentTarget (React element) and event.nativeEvent.currentTarget (null).

The currentTarget read-only property of the Event interface identifies the current target for the event, as the event traverses the DOM. It always refers to the element to which the event handler has been attached.

https://developer.mozilla.org/en-US/docs/Web/API/Event/currentTarget

When you do document.addEventListener(), event.currentTarget is null.

ReactDOM will pass the synthetic events down to the individual handlers you attached to React elements. So, calling event.nativeEvent.stopImmediatePropagation() there would actually prevent any subsequent event of the same type from happening on the document, and not on the element with the synthetic event handler.

If that’s correct, event.nativeEvent.stopImmediatePropagation() should almost never be used. And I don’t think there’s an easy way to support sIP on synthetic events unless ReactDOM attaches the native event to the actual element that received the event prop.

Can we this get reopened?

I think sIP method on the Synthetic even would just prozy to event.nativeEvent.stopImmediatePropagation since there isn’t anything in the Synthetic event system that would change or need to be implemented, given that components only ever have one handler per event anyway. I wouldn’t be opposed to adding it as a convenience but I do think it hides the fact that sIP isn’t supported over all React’s browsers (though maybe it is now that IE8 is gone)

I think @Mr-Wallet is right here. Changing how SyntheticEvent works is not necessary, but at least this behavior should be acknowledged in the documentation.

It was a big surprise when I’ve found my answers on StackOverflow, not the official docs. Especially considering that the docs promise that this method acts the same as a native one.

https://stackoverflow.com/questions/24415631/reactjs-syntheticevent-stoppropagation-only-works-with-react-events

That’s true enough, but in our case we fully understood that and that’s exactly what we wanted (for reasons that are too specific to be worth elaborating, but it involved avoiding a refactor in the short term). We still suffered from misleading documentation even though we mostly understood the consequences of what we were trying to do.

if you want to kill hover events for touch input, onTouchStart will trigger onMouseOver and stopImmediatePropagation cancels that internal cascade.

Could you please provide me with an example that demonstrates this?