Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React: Nested onclick also triggers parent

I used the react version of the slick carousel to make a Netflix like carousel. You can click on a tile and that tile then expands to show the details of that tile.

Example:

enter image description here

This works great thanks to Slicks ability to handle dynamic heights. I want to add a close button the expanded section (as seen in the far right). But that is where I have an issue.

If I add a close button with a onClick handler, it will always trigger the parent Onclick which shows the expanded section.

The showExpanded onclick function just sets a showDetails state.

So my question is:

How can I set a state by clicking on the close button, without also triggering the wrapping parent.

I tried event.preventDefault() and event.stopPropagation() but that didn't do the trick.

Tile click looks like this:

expandTile(){
  this.setState({
    showDetails: true,
    closeTile: false
  });
}

Close button click function as I have it now:

closeTile(e){
   e.preventDefault();
   e.stopPropagation();
   const showDetails = this.state.showDetails;
   if(showDetails){
      this.setState({
        showDetails: false,
        closeTile: true
      });
   }
}

Update: added JSX:

  return (
    <div className={s.itemPreWrapper} key={`${el.title}-item-${index}`}>
      <div className={`${s.item} ${showDetails ? s.showDetails : ''}`}
           onClick={self.state.expandItem}
           data-index={index}
        <div className={s.itemCaret}></div>
        <div className={s.imgWrapper}>
          <img src={el.itemImage}/>
        </div>
        <div className={s.overlay}>
          {el.title}
        </div>
        <div className={s.expandedTile} style={{left: '-'+offset+'px'}}>
          <div className={s.etItem}>
           <div key={`subitem-${index}`} ref="subItem">
            <div className="row">
              <div className={`${s.etClose}`} onClick={self.state.closeTile}><span></span></div>
              <div className="col-xs-12 col-sm-3">
                <div className={`${s.etImage}`}>
                  <img src={el.itemImage} alt="product image" className="img-responsive"/>
                </div>
              </div>
              <div className="col-xs-12 col-sm-9">
                <div className="row">
                  <div className={`${s.etContent} col-xs-12 col-sm-6 col-lg-8`}>
                    <h2>{itemTitle}</h2>
                    <p> {el.description}</p>
                  </div>
                  <div className={`${s.etMedia} col-xs-12 hidden-sm col-sm-5 col-lg-3`}>
                    {media}
                  </div>
                </div>
            </div>
            <div className="col-xs-12 col-md-11">
              {optionsElem}
            </div>
          </div>
          </div>
        </div>
      </div>
    </div>
  );
like image 767
jansmolders86 Avatar asked Oct 28 '16 11:10

jansmolders86


People also ask

How do I stop parent onClick event in React?

event.stopPropagation() This will stop any parent component's event from firing. To use this: Make sure to pass the event object as a parameter. Use the stopPropagation method on the event object above your code within your event handler function.

Can we pass two functions onClick event in React?

The first solution to perform multiple onClick events in React is to include all of your actions inside of a function and then call that single function from the onClick event handler. Let's explore how to do that in a React Component: import React from 'react'; function App() { function greeting() { console.

Can I add onClick to a component React?

The React onClick event handler enables you to call a function and trigger an action when a user clicks an element, such as a button, in your app. Event names are written in camelCase, so the onclick event is written as onClick in a React app. In addition, React event handlers appear inside curly braces.


2 Answers

A click event is essentially the result of a mousedown event followed by a mouseup event on the same element, which can propagate around even if stopPropagation is called on a click event.

One solution is to call it on mousedown as well; in its simplest form:

<div onMouseDown={e => e.stopPropagation()} ... />
like image 63
John Weisz Avatar answered Sep 27 '22 16:09

John Weisz


The solution that worked for me was to place a call to event.stopPropagation() in your child onClick method. This will prevent the parent from being called.

like image 26
Garrett Tacoronte Avatar answered Sep 27 '22 15:09

Garrett Tacoronte