Skip to content

Conversation

@rlobenwein
Copy link

  • I've included event handler examples to enhance understanding.
  • I've suggested expanding the event propagation explanation and included a code example there. I'll put the text suggestion in a separate comment here.
  • Event pooling was removed in React 17. The section from the chapter and the code example should be removed.

@rlobenwein
Copy link
Author

This is the suggestion for the Event propagation section:

Event Propagation

In JavaScript, events usually propagate in two ways:

  • Capturing phase – the event travels from the window down through the DOM tree.
  • Bubbling phase – the event bubbles back up from the target element to its ancestors, triggering any event listeners along the way.
    For example, clicking on a <button> inside a <div> can trigger both the button’s handler and the parent div’s handler if both are listening to the same event.
<div onclick="console.log('Div clicked')">
    <button onclick="console.log('Button clicked')">Click me</button>
</div>

This happens because the event bubbles up from the button to its parent div.

In React, event propagation follows the same model, bubbling and capturing, but they are attached differently: while traditional JavaScript attaches a separate listener directly to every single DOM element (e.g., 100 buttons = 100 listeners), React attaches a single native event listener to the root of the React application (usually the document or the element where ReactDOM.render is called)
When a Synthetic Event is dispatched, it traverses the React Component Tree:

  • Capture Phase: The event travels down from the root to the target element. You attach a handler for this phase by appending Capture to the event prop (e.g., onClickCapture={handleCaptureClick}).
  • Bubbling Phase (Default): The event travels up from the target element back to the root. This is the default behavior when you use props like onClick or onSubmit.
    The behavior of onClick in React is the same as the bubbling phase in native JavaScript.
function EventPropagationDemo() {
  const handleGrandparent = (e) => {
    alert('Grandparent - bubbling phase');
  };

  const handleParent = (e) => {
    alert('Parent - bubbling phase');
  };

  const handleChild = (e) => {
    alert('Child - target');
  };

  const handleParentCapture = (e) => {
    alert('Parent - capture phase');
  };
  const handleGrandparentCapture = (e) => {
    alert('Grandparent - capture phase');
  };

  return (
    <>
    <h2>Event Propagation: capturing and bubbling</h2>
    <div onClick={handleGrandparent} onClickCapture={handleGrandparentCapture} style={{ padding: "20px", border: "2px solid black" }}>
        <p>Grandparent</p>
      <div onClick={handleParent} onClickCapture={handleParentCapture} style={{ padding: "20px", border: "1px solid black" }}>
        <p>Parent</p>
          <button onClick={handleChild}>(Child) Click Me</button>
      </div>
    </div>
    </>
  );
}
export default EventPropagationDemo;

You can use e.stopPropagation() to prevent the event from bubbling further:

function EventPropagationDemo() {
  const handleGrandparent = (e) => {
    alert('Grandparent - bubbling phase');
  };

  const handleParent = (e) => {
    alert('Parent - bubbling phase');
  };

  const handleChild = (e) => {
    alert('Child - target');
    e.stopPropagation();
  };

  const handleParentCapture = (e) => {
    alert('Parent - capture phase');
  };
  const handleGrandparentCapture = (e) => {
    alert('Grandparent - capture phase');
  };

  return (
    <>
    <h2>Event Propagation: capturing and bubbling</h2>
    <div onClick={handleGrandparent} onClickCapture={handleGrandparentCapture} style={{ padding: "20px", border: "2px solid black" }}>
        <p>Grandparent</p>
      <div onClick={handleParent} onClickCapture={handleParentCapture} style={{ padding: "20px", border: "1px solid black" }}>
        <p>Parent</p>
          <button onClick={handleChild}>(Child) Click Me</button>
      </div>
    </div>
    </>
  );
}
export default EventPropagationDemo;

React's event delegation provides several benefits. First, it reduces the number of event listeners attached to individual DOM elements, resulting in improved performance. Second, it allows you to handle events for dynamically created or removed elements without worrying about attaching or detaching event listeners manually.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant