Event Propagation in React
Introduction
When mixing React's event handler method with vanilla Javascript's event handler method, event propagation may not work as intended.
For example, in a structure like button1
, button2
, clicking button2
can trigger the event handler of button1
as well.
const buttonEl = document.getElementById('button1');
buttonEl.addEventListener('click', () => {
console.log('button1 clicked');
});
const handleClick = (e) => {
e.stopPropagation();
console.log('button2 clicked');
};
return (
<button id='button1'>
<button id='button2' onClick={handleClick}>Click me</button>
</button>
);
// When button2 is clicked
button2 clicked
button1 clicked
Solution
Event propagation in React differs from that in vanilla Javascript because React handles event propagation using a delegation method. (comment)
In React (post React 17), event listeners are registered on the rootDOM. Therefore, event listeners within React propagate as expected according to the DOM structure, but vanilla Javascript event propagation may not behave as anticipated.
While it's best to avoid mixing the two types of events, sometimes it's unavoidable when using third-party libraries or handling parts of the code you can't control. In such cases, you must block event propagation according to the behavior of each method.
// Unify event listener to vanilla Javascript
const buttonEl = document.getElementById('button1');
buttonEl.addEventListener('click', () => {
console.log('button1 clicked');
});
const button2El = document.getElementById('button2');
button2El.addEventListener('click', (e) => {
e.stopPropagation();
console.log('button2 clicked');
});
return (
<button id='button1'>
<button id='button2'>Click me</button>
</button>
);
// Or
// Unify event listener to React
const handleClick1 = (e) => {
console.log('button1 clicked');
};
const handleClick = (e) => {
e.stopPropagation();
console.log('button2 clicked');
};
return (
<button id='button1' onClick={handleClick1}>
<button id='button2' onClick={handleClick}>Click me</button>
</button>
);