Search code examples
javascriptreactjsevent-handlingdom-eventsevent-bubbling

Prevent event from bubbling up the dom tree


I have a card component as follows

<div
      onClick={e => {
        console.log("DEMAND CARD CLICKED");
        if (isSelectionActive) {
          setSelected();
        }
      }}
>  
      <DemandCardFooter
        demandId={id}
        totalBooked={totalBooked}
        totalDemand={totalDemand}
      />    
</div>

This is what <DemandCardFooter/> looks like:

<div className="vt-card-footer d-flex justify-content-between align-items-baseline px-3">
      <DemandSelector demandId={demandId} />
      <p className="lead font-weight-bold mb-0">
        <span className="text-success">{totalBooked}</span> / {totalDemand}{" "}
        <small className="text-muted font-weight-normal">Units.</small>
      </p>
</div>

And finally this is how <DemandSelector/> looks like:

const DemandSelector = ({ demandId }) => {
  const [isChecked, setChecked] = useRowSelector({
    path: "demands",
    payload: { id: demandId }
  });
  return (
    <Checkbox
      checked={isChecked ? true : false}
      onClick={e => {
        console.log("CHECKBOX CLICKED");
        e.stopPropagation();
        e.nativeEvent.stopImmediatePropagation();
        setChecked();
      }}
    />
  );
};

My problem is when i click the checkbox both the checkbox's onClick and card's onClick are triggered, is there any way i can restrict the callback to the lowest level?

enter image description here


Solution

  • Figured it out after a while. The solution was to put stopPropogation() in the DOM element encasing <DemandSelector/>

    So This code worked

     <div
          className="vt-card-footer d-flex justify-content-between align-items-baseline px-3"
          onClick={e => {
            e.stopPropagation();
          }}
        >
          <DemandSelector demandId={demandId} />
          <p className="lead font-weight-bold mb-0">
            <span className="text-success">{totalBooked}</span> / {totalDemand}{" "}
            <small className="text-muted font-weight-normal">Units.</small>
          </p>
        </div>
    

    Also don't forget to put it all the way down

    const DemandSelector = ({ demandId }) => {
      const [isChecked, setChecked] = useRowSelector({
        path: "demands",
        payload: { id: demandId }
      });
    
      return (
        <Checkbox
          checked={isChecked ? true : false}
          onClick={e => {
            e.stopPropagation();
            setChecked();
          }}
        />
      );
    };