2

I'm trying to understand the order in which events are being executed in a React application. Given the following sample component, why would I be observing "OUTER ELEMENT" logged before "INNER ELEMENT" when I click on the inner div element?

I can see that the event is in the bubbling phase, so my understanding is that it should propagate from the target element upwards, but I am observing the opposite happen.

Is my understanding incorrect?

export const Test = () => {
    const ref = useRef<HTMLDivElement>(null);

    useEffect(() => {
        const currentRef = ref.current;

        if (!currentRef) {
            return;
        }

        const handler = (e) => {
            console.log("OUTER ELEMENT");
        };

        currentRef.addEventListener("click", handler);

        return () => {
            currentRef.removeEventListener("click", handler);
        };
    });

    return (
        <div ref={ref}>
            <div
                onClick={(event) => {
                    console.log("INNER ELEMENT");
                }}
            >
                INNER
            </div>
            OUTER
        </div>
    );
};
cnfw
  • 770
  • 2
  • 11
  • 28

1 Answers1

1

React uses a synthetic event system to fix some browser inconsistencies in event handling. (See also here.)

At the implementation level, it's my understanding that React is actually attaching a single top-level handler for each event (to document or the React root or similar) and then dispatching that event through the React tree to the appropriate onFoo handler.

As a result, you can't make assumptions about the order of execution between React events and native JS events, and using functions like Event.stopPropagation from React to influence JS may not work as expected. (Former React manager Sophie Alpert said, "We don't guarantee anything about event ordering between React events and native events.")

Josh Kelley
  • 56,064
  • 19
  • 146
  • 246
  • Thank you for this and the links to relevant info, it makes sense to me now. I guess the main takeaway from this is to avoid using DOM native `Event` methods like `addEventListener` and do everything with synthetic events. – cnfw Mar 29 '23 at 11:59