简体   繁体   中英

Clicking on a div that contains span, doesn't trigger onclick event - React

I have a div, and inside I am rendering spans based on some conditions. If the component has some children, I'd like this div to expand. It works fine if I click on this div on an area outside of the inner span.

An example, is the following Image . When clicking on the row, it expands the area to show items like this . However, when I click on the header text, it's not working, the on click event doesn't fire.

Here's my code:

 <div className={headerStyles.header} onClick={(e) => this.selectHeader(e, this.props.items.length)}>
    {this.props.items.length > 0 && 
          <span className={headerStyles.expand} style={{ color: this.props.headerNameColor }}></span>
                    }
          <span style={{ color: this.props.headerNameColor }}  >{this.props.headerName}</span>
                    {this.props.headerUrl &&
                        <a
                            style={{ color: this.props.headerNameColor }}
                            href={this.props.headerUrl}
                            data-interception="off"
                            target="_blank"
                            title="Open link in a new tab">
                            <i className={['ms-Icon', 'ms-Icon--OpenInNewWindow', headerStyles.openNewTab].join(' ')}></i>
                        </a>
                    }
                </div>

Here's the function that gets called when clicking the header:

 selectHeader(e, numOfItems) {
        if (e.target.children.length > 0 && numOfItems > 0) {
            e.target.children[0].classList.toggle(headerStyles.expand)
            e.target.children[0].classList.toggle(headerStyles.collapse)
            e.target.parentElement.querySelector(`.${headerStyles.items}`).classList.toggle(headerStyles.hidden)
        }
        else if(this.props.headerUrl){

        }
    }

Any guidance is appreciated.

Thanks

As I suspected, you're trying to do something with the event.target value inside of selectHeader . That won't work very well because event.target will change depending on which element you clicked on inside of your div. It won't always be the outer "parent" element.

You're also trying to read data imperatively from the DOM, which is not a very "React" way of doing things. In fact, within your function you're doing a classList.toggle(headerStyles.hidden) which is in direct conflict with React managing the state and rendering of your app. All the data you need should live within the state of your React application - you shouldn't need to query the DOM at all.

Ditch event.target and classList.toggle and find a way to do it using React state. For example, when you click the div you could simply toggle the "expanded" state of your component, and use that state to determine which CSS class to render:

<div onClick={() => {this.setState({isExpanded: !this.state.isExpanded})}} >
  <span className={this.state.isExpanded ? headerStyles.expand : headerStyles.collapse} ></span>
</div>

Avoid using arrow functions inside the JSX here. e object is always passed since this is an event handler, and your props are accessible from your handler:

selectHeader = (e) => {
     const numOfItems = this.props.items.length;
     // rest of the code...

 }

inside render method:

<div onClick={this.selectHeader}>

Try to add pointerEvents: 'none' style to the span tags so it won't get any mouse event. This will make the event.target to always be the div

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