Event bubbling in Javascript and React

With vast applications in modern web development, understanding event propagation is crucial for experienced developers. The fundamental concept behind event propagation in JavaScript and React is Event Bubbling. This article provides an in-depth explanation of event bubbling, how it works in JavaScript, and its benefits.

What is Event Bubbling?

Event bubbling is a type of event propagation in the Document Object Model (DOM) where an event propagates from its originator (target element) up to the root of the tree (document object). In simpler terms, when an event is fired on an element, it first runs the handlers on it, then on its parent, then all the way up on other ancestors.
For example, imagine a button element wrapped inside a div element. When the button is clicked, the click event is first triggered on the button (the deepest level), and if unhandled, it bubbles up to the div element.

document.querySelector("div").addEventListener('click', () => { console.log("Div clicked!!!") }); 
document.querySelector("button").addEventListener('click', () => { console.log("Button clicked!!!") }); 

In the code above, if we clicked on the button, we would see in the console that both the button and the div were clicked, thanks to event bubbling.

How event bubbling works in JavaScript

In JavaScript, event bubbling is inherent to the way events work in the DOM. When an event is fired on an element, it will bubble up through its ancestors until it reaches the window object, unless the propagation is explicitly stopped.
This happens in three stages:

  • the capture phase - the event travels from the window object to the target element.
  • the target phase - the event is handled at the target element.
  • the bubbling phase - the event bubbles up from the target element back to the window object.

However, the developer can decide to stop the event bubbling using the stopPropagation() method.

document.querySelector("button").addEventListener('click', (event) => { 
  console.log("Button clicked!");
  event.stopPropagation(); // Stops the bubbling here.
}); 

By including event.stopPropagation(), the upward propagation of the event is stopped.

Benefits of event bubbling

Understanding and using event bubbling correctly has several benefits.

  • You can set an event listener on a parent element, rather than adding event listeners to each child element individually.
  • Dynamic content handling: When elements are dynamically added or removed, event bubbling allows event handlers attached to a parent to handle events on child elements.
  • Performance optimization: Fewer event listeners means less memory usage, improving application performance.

Event bubbling in React

React uses a virtual DOM, and its event bubbling mechanism is slightly different from native JavaScript event bubbling. However, the concept remains the same, and understanding it can prove useful when troubleshooting event-related bugs.
In React, events do not actually bubble; instead, React simulates event propagation using its synthetic event system, which follows the W3C specification, making code more predictable.

import React from 'react';

class ChildComponent extends React.Component {
  handleClick = (e) => {
    alert('Child button clicked!!!');
    e.stopPropagation();
  }
  
  render() {
    return (
      <button onClick={this.handleClick}>ChildComponent Button</button>
    );
  }
}

class ParentComponent extends React.Component {
  handleClick = () => {
    alert('Parent DIV clicked!!!');
  }
  
  render() {
    return (
      <div onClick={this.handleClick}>
        Parent Div
        <ChildComponent />
      </div>
    );
  }
}

export default ParentComponent;

In the code above, when the button in the ChildComponent is clicked, it will call its handleClick method and display an alert saying Child button clicked!!! The e.stopPropagation() prevents the event from being propagated to the ParentComponent.
Without e.stopPropagation(), if you click on the ChildComponent button, you will get two alerts, one for the button in the ChildComponent and another for the div in the ParentComponent. This is because of event bubbling. But with e.stopPropagation(), the event is stopped at the child and does not bubble up to the parent.

Summary

Properly understood, event bubbling is an important weapon in a developer's arsenal. With intrinsic benefits such as fewer lines of code, effortless dynamic content handling and optimized performance, event bubbling is the key to effective event propagation in both JavaScript and React.

Happy bubbling!