Do you want to request a feature or report a bug?
A bug.
What is the current behavior?
Event listener attached to document will still be called after calling event.stopPropagation() on target.
Example: (codesandbox link)
class App extends React.Component {
componentDidMount() {
document.addEventListener("click", this.handleClickOnDocument);
window.addEventListener("click", this.handleClickOnWindow);
}
componentWillUnmount() {
document.removeEventListener("click", this.handleClickOnDocument);
window.removeEventListener("click", this.handleClickOnWindow);
}
handleClickOnDocument = e => {
console.log("handling event on document");
};
handleClickOnWindow = e => {
console.log("handling event on window");
};
render() {
return (
<div onClick={() => console.log("handling event on div")}>
<button
onClick={e => {
e.stopPropagation();
}}
>
Click Me
</button>
</div>
);
}
}
console will log:
handling event on document
What is the expected behavior?
handleClickOnDocument won't be called and no log in console.
Which versions of React, and which browser / OS are affected by this issue? Did this work in previous versions of React?
e inside <div onClick> handler is a React synthetic event in your example. You're stopping its propagation through the React hierarchy, but for performance reasons it's technically implemented as an event listener on the document. So calling e.stopPropagation() doesn't affect the browser event and doesn't prevent it from reaching the document.
If you need to forbid it from reaching the document, you could put a ref on the div, and use addEventListener to add a DOM event listener directly. Then e.stopPropagation() in it will do what you expect.
Hope this helps!
Thanks for your reply.
I know that e inside <div onClick> is an React synthetic event. But it is still somehow weird that React can't stop propagate event to document. As far as I can see, attaching event to document is still commonly used, like react-click-outside.
By the way, will this issue get resolved if https://github.com/facebook/react/issues/2043 gets addressed?
@VincentBel this is because React's own listener is registered on the document as well, not on the element where the event originated from. Here's an example that explains what's happening.
We're changing this in React 17 by attaching events to the root.
If you want to try it, we released 17 RC yesterday with this change:
https://reactjs.org/blog/2020/08/10/react-v17-rc.html
Most helpful comment
einside<div onClick>handler is a React synthetic event in your example. You're stopping its propagation through the React hierarchy, but for performance reasons it's technically implemented as an event listener on the document. So callinge.stopPropagation()doesn't affect the browser event and doesn't prevent it from reaching the document.If you need to forbid it from reaching the document, you could put a ref on the
div, and useaddEventListenerto add a DOM event listener directly. Thene.stopPropagation()in it will do what you expect.Hope this helps!