DEV Community

Chibuikem Victor Ugwu
Chibuikem Victor Ugwu

Posted on

Building Bulletproof Dropdown Click Handling in React

By using data attributes and .closest(), the click-handling logic becomes resilient to DOM changes and easier to maintain.

It focuses on the data (filter.id) rather than the DOM structure, making the component more reliable and scalable.

In React, avoid relying on DOM hierarchy for logic. I learnt this the hard back when I used parentElement for this. Use data attributes with .closest() for robust click handling.

The core idea is to listen for clicks on the entire document, then determine whether a click happened inside or outside your dropdown.

This approach is necessary because the dropdown doesn’t know when a user clicks elsewhere.The browser always bubbles clicks upward:

button -> div -> body -> document.

It works even if icons, labels, or nested elements change.

The dropdown ref points to the actual DOM node of the dropdown panel:
{activeDropdown && (

)}

Any click inside this element should not close the dropdown.

To determine where a click occurred:

Inside the document listener, check:

  1. Was the click on a filter button?

const clickedFilterButton = event.target.closest("[data-filter]");
This finds the nearest ancestor with the data-filter attribute.

  1. Was the click inside the dropdown panel?

Use contains() to check whether the clicked element is inside the dropdown.

If true, do nothing. The dropdown should stay open.

Why My Previous parentElement Logic Failed
The previous approach relied on event.target.parentElement.id to match the active dropdown’s ID.

However, event.target is unpredictable:

If the user clicks the icon inside a button, event.target becomes the element, not the .

event.target.parentElement.id may then point to a with no ID, rather than the intended button.

This approach is Harder to scale. Every nested element requires careful handling.

It is DOM-dependent, therfore, changes to the DOM structure break the logic.

This makes assumptions about parent-child relationships.

Dropdown Toggle Logic
activeDropdown stores the ID of the currently active dropdown (or null if none).

Clicking the same dropdown again closes it. Clicking a different one switches to the new dropdown.

The dropdown closes only if the click is outside.

Clicking a different dropdown switches the active state.

Top comments (0)