简体   繁体   中英

How to avoid conflicting onclick functions on a React component

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??

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(); } 

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, ac ross-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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM