Ojasa Mirai

Ojasa Mirai

ReactJS

Loading...

Learning Level

🟢 Beginner🔵 Advanced
🎪 Event Handling Basics🖱️ Click Events⌨️ Keyboard Events📝 Form Events🎯 Event Handlers with Parameters🚫 Event Default Behavior🔗 Event Delegation⚡ Performance & Events
Reactjs/Events/Event Delegation

🔗 Event Delegation — Handle Multiple Events Efficiently

Event delegation means attaching a single handler to a parent element and responding to events from multiple children. It's efficient and elegant.


🎯 Understanding Event Bubbling

Events "bubble" up from children to parents. This is key to delegation:

function BubblingExample() {
  const handleClick = (e) => {
    console.log("Clicked element:", e.target.tagName);
  };

  return (
    <div onClick={handleClick}>
      <button>Button 1</button>
      <button>Button 2</button>
      <button>Button 3</button>
    </div>
  );
}

When you click any button, the click event bubbles up to the parent `div`, and the handler fires. The `e.target` tells you which element was actually clicked.

💡 Single Handler for Multiple Elements

Instead of attaching handlers to each item, delegate to the parent:

function ItemList() {
  const [items] = useState([
    { id: 1, label: "Item 1" },
    { id: 2, label: "Item 2" },
    { id: 3, label: "Item 3" },
  ]);

  const handleItemClick = (e) => {
    // Check if clicked element is a button
    if (e.target.tagName === "BUTTON") {
      const id = e.target.dataset.id;
      console.log("Clicked item:", id);
    }
  };

  return (
    <ul onClick={handleItemClick}>
      {items.map((item) => (
        <li key={item.id}>
          <button data-id={item.id}>{item.label}</button>
        </li>
      ))}
    </ul>
  );
}

Use `data-*` attributes to pass data and check `e.target` to identify which element was clicked.

<details>

<summary>📚 More Examples</summary>

// Handling different actions on different elements
function TodoList() {
  const [todos, setTodos] = useState([
    { id: 1, text: "Learn React", done: false },
    { id: 2, text: "Build app", done: false },
  ]);

  const handleListClick = (e) => {
    const button = e.target.closest("button");
    if (!button) return;

    const id = parseInt(button.dataset.id);
    const action = button.dataset.action;

    if (action === "toggle") {
      setTodos(
        todos.map((todo) =>
          todo.id === id ? { ...todo, done: !todo.done } : todo
        )
      );
    } else if (action === "delete") {
      setTodos(todos.filter((todo) => todo.id !== id));
    }
  };

  return (
    <ul onClick={handleListClick}>
      {todos.map((todo) => (
        <li key={todo.id}>
          {todo.text}
          <button data-id={todo.id} data-action="toggle">
            {todo.done ? "Undo" : "Done"}
          </button>
          <button data-id={todo.id} data-action="delete">
            Delete
          </button>
        </li>
      ))}
    </ul>
  );
}

</details>

🎨 Using e.closest() for Reliable Element Finding

`e.target.closest()` is more reliable than checking `tagName`:

function Form() {
  const handleFormClick = (e) => {
    // Find the nearest button, even if you clicked inside it
    const button = e.target.closest("button");
    if (button) {
      console.log("Button clicked:", button.textContent);
    }
  };

  return (
    <form onClick={handleFormClick}>
      <button type="button">
        <span>Click me</span>
      </button>
      <button type="button">Or me</button>
    </form>
  );
}

🔧 Data Attributes for Context

Store data in `data-*` attributes and retrieve with `dataset`:

function ColorPicker() {
  const [selected, setSelected] = useState("red");

  const handleColorClick = (e) => {
    const button = e.target.closest("button");
    if (button) {
      const color = button.dataset.color;
      setSelected(color);
    }
  };

  const colors = ["red", "blue", "green"];

  return (
    <div>
      <div onClick={handleColorClick}>
        {colors.map((color) => (
          <button
            key={color}
            data-color={color}
            style={{
              background: color,
              opacity: selected === color ? 1 : 0.5,
            }}
          >
            {color}
          </button>
        ))}
      </div>
      <p>Selected: {selected}</p>
    </div>
  );
}

🎨 Real-World Example: Dynamic List with Actions

function TaskManager() {
  const [tasks, setTasks] = useState([
    { id: 1, text: "Learn React", priority: "high" },
    { id: 2, text: "Build project", priority: "high" },
    { id: 3, text: "Deploy app", priority: "low" },
  ]);

  const handleTaskAction = (e) => {
    const button = e.target.closest("button");
    if (!button) return;

    const taskId = parseInt(button.dataset.id);
    const action = button.dataset.action;

    if (action === "delete") {
      setTasks(tasks.filter((task) => task.id !== taskId));
    } else if (action === "increase-priority") {
      setTasks(
        tasks.map((task) =>
          task.id === taskId
            ? { ...task, priority: "high" }
            : task
        )
      );
    }
  };

  return (
    <div onClick={handleTaskAction}>
      {tasks.map((task) => (
        <div key={task.id} style={{ borderBottom: "1px solid gray" }}>
          <p>
            {task.text} <strong>[{task.priority}]</strong>
          </p>
          <button data-id={task.id} data-action="increase-priority">
            Increase Priority
          </button>
          <button data-id={task.id} data-action="delete">
            Delete
          </button>
        </div>
      ))}
    </div>
  );
}

🔑 Key Takeaways

  • ✅ Events bubble from children to parents
  • ✅ Attach one handler to parent instead of many to children
  • ✅ Use `e.target` to identify which element was clicked
  • ✅ Use `data-*` attributes to store context data
  • ✅ Use `e.target.closest()` to find elements reliably
  • ✅ Event delegation is efficient and reduces memory usage
  • ✅ Works best for dynamic lists and repetitive elements

Ready to practice? Performance & Events | Challenges


Resources

Python Docs

Ojasa Mirai

Master AI-powered development skills through structured learning, real projects, and verified credentials. Whether you're upskilling your team or launching your career, we deliver the skills companies actually need.

Learn Deep • Build Real • Verify Skills • Launch Forward

Courses

PythonFastapiReactJSCloud

© 2026 Ojasa Mirai. All rights reserved.

TwitterGitHubLinkedIn