Reputation: 3159
I have a component below: there are 2 usecases, when I click on the entire div
some function is executed and when I click on just the <img>
, some function is executed.
I have 2 props defined, onClick
, when clicked on the entire div
and onIconClick
when clicked on the img.
export default class List extends React.Component {
onClick() {
this.props.onClick();
}
onIconClick() {
this.props.onIconClick();
}
render() {
return (
<div style="width:200px, height: 200px" onClick={this.onClick.bind(this)}>
<img src="delete.png" onClick={this.onIconClick.bind(this)} />
</div>
);
}
}
here is the way I call the component:
export default class MyApp extends React.Component {
onClick() {
//some execution
}
onIconClick() {
//some other execution
}
render() {
return (
<List
onClick={this.onClick.bind(this)}
onIconClick={this.onIconClick.bind(this)}
/>
);
}
}
Now my issue is the this.onClick.bind(this)
gets called all the time even when I click the image, hence I never get to this.onIconClick.bind(this)
.
I tried reversing the order:
<List onIconClick={this.onIconClick.bind(this)} onClick={this.onClick.bind(this)} />
still doesn't work, not sure what selection criteria I should use in order to distinguish between these 2 clicks.
Any ideas??
Upvotes: 2
Views: 1561
Reputation: 6246
You can use e.stopPropagation()
. If you want to use e.nativeEvent.stopImmediatePropagation()
, you can use in the same line.
onIconClick(e) {
e.stopPropagation();
//e.nativeEvent.stopImmediatePropagation();
this.props.onIconClick();
}
Upvotes: 2
Reputation: 10179
Try this:
class Parent extends React.Component {
constructor(props) {
super(props);
this.onClick = this.onClick.bind(this);
this.onIconClick = this.onIconClick.bind(this);
}
onClick() {
alert("Parent-onClick()");
}
onIconClick() {
alert("Parent-onIconClick()");
}
render() {
return (
<div>
<Child onClick={this.onClick} onIconClick={this.onIconClick} />
</div>
);
}
}
class Child extends React.Component {
constructor(props) {
super(props);
this.onClick = this.onClick.bind(this);
this.onIconClick = this.onIconClick.bind(this);
}
onClick() {
this.props.onClick();
}
onIconClick(e) {
e.stopPropagation();
this.props.onIconClick();
}
render() {
let styles = {
height: "500px",
backgroundColor: "blue",
paddingTop: "20px"
};
return (
<div onClick={this.onClick} className="img-wrapper" style={styles}>
<img
onClick={this.onIconClick}
src="https://via.placeholder.com/350x150"
alt="img"
/>
</div>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<Parent />, rootElement);
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id="root"><div>
The idea is using stopPropagation()
method of the SyntheticEvent instance.
Your event handlers will be passed instances of SyntheticEvent, a cross-browser wrapper around the browser’s native event. It has the same interface as the browser’s native event, including stopPropagation() and preventDefault(), except the events work identically across all browsers.
If you find that you need the underlying browser event for some reason, simply use the nativeEvent attribute to get it.
Using the SyntheticEvent 's methods allows our code to behave exactly the same across all browsers.
Upvotes: 4