I have nested click event handlers within a component:
class ListItem extends React.Component {
...
render() {
return (
<div onClick={this.save}>
...Content...
<span onClick={this.onDeleteClick}> (Delete)</span>
</div>
);
}
...
}
(Complete, minimal example at the bottom of this post.)
This component is used as a "list item" within a containing component. When I click on the (Delete)
it fires the onDeleteClick
as expected, which makes a callback to the parent which results in the component being removed from the parent component. The click event then starts bubbling up, as expected. However, it bubbles "up" to the next component in the parent list. After all, the original target was already removed by the delete handler.
If I add an e.stopPropagation()
to the top of the onDeleteClick
handler it all works fine, but I'm just trying to understand why the click event is being delivered to a completely different component, just to make sure there aren't any other smoking guns in there.
My current theory is that the pending event queue is somehow indexed into the virtual DOM in such a way that if you mutate the virtual DOM during an event handler, bubbling events could get delivered to the incorrect component in the virtual DOM. I would have expected the bubbling event to simply not fire, rather than firing on a completely different component.
Is this what's going on? Any other insight? Is this a flawed design, and if so, any recommendations on alternatives?
Here's a minimal example showing the problem: https://codepen.io/mgalgs/pen/dRJJyB
And here's the fixed version: https://codepen.io/mgalgs/pen/KqZBKp
The full diff for the "fix" is:
--- orig.jsx
+++ new.jsx
@@ -32,6 +32,7 @@
}
onDeleteClick(e) {
+ e.stopPropagation();
this.props.onDeleteClick(e);
}
}