Javascript

What is event stopPropagation?

As I was learning React by cloning an E-Commerce website, modal did not work as intended. I decided to prevent making the same mistake.

What I tried

I wanted to create a onClick event that handles opening and closing modal. However, when I write the code below, the modal stayed open when I clicked outside the modal.

function Modal({ setShow }) {
  return (
    <div
      className="absolute bg-[rgba(0,0,0,0.4)] inset-0 flex items-center justify-center"
      onClick={() => setShow(false)}
    >
      <div className="bg-white w-[300px]">This is a modal</div>
    </div>
  );
}
 
function App() {
  const [show, setShow] = useState(false);
 
  return (
    <div>
      <div onClick={() => setShow(true)}>
        <p>Click to open modal</p>
        {show && <Modal setShow={setShow} />}
      </div>
    </div>
  );
}

After reading this MDN article, I realized it is because of how javascript handles the event: Event Bubbling and Event Capturing

Event Bubbling

<div>
  <h1>This is h1</h1>
  <h2>This is h2</h2>
</div>

Assume every tag in above code has onClick event that prints their tag name. If I click on h1 tag, both h1 and div will be printed on the console because of Event Bubbling. It passes the event to the parent.

Event Capturing

Event Capturing handles events in the opposite way. It passes events to the child. To make Event Capturing, an option should be added like following.

element.addEventListener("click", handleClick, { capture: true });

stopPropagation

stopPropagation is used when to stop Event Bubbling or Event Capturing. Adding a highlighted line below makes everything works as intended.

function Modal({ setShow }) {
  return (
    <div
      className="absolute bg-[rgba(0,0,0,0.4)] inset-0 flex items-center justify-center"
      onClick={(e) => {
        e.stopPropagation();
        setShow(false);
      }}
    >
      <div className="bg-white w-[300px]">This is a modal</div>
    </div>
  );
}
 
function App() {
  const [show, setShow] = useState(false);
 
  return (
    <div>
      <div onClick={() => setShow(true)}>
        <p>Click to open modal</p>
        {show && <Modal setShow={setShow} />}
      </div>
    </div>
  );
}

Then, what is this for?

I was wondering if there is any useful cases for Event Bubbling and Event Capturing. It becomes especially useful when to handle dropdown menus.

function Dropdown() {
  return (
    <div
      onClick={(e) => {
        e.stopPropagation();
        console.log(e.target.innerText);
      }}
    >
      <div>Hello</div>
      <div>There</div>
    </div>
  );
}
 
function App() {
  const [show, setShow] = useState(false);
 
  return (
    <div>
      <div onClick={() => setShow((prev) => !prev)}>
        <p>Click to open Dropdown</p>
        {show && <Dropdown />}
      </div>
    </div>
  );
}

I can track what menu has been clicked without writing onClick event on every menu.

Thoughts

Sometimes, I just directly copied not knowing what the code does. And I knew how important it is to know how the language itself rather than the library or framework.