This is the code, which I reduced and simplified as much as I could:
import { useEffect, useRef, useState } from 'react';
export default function App() {
const parentElementRef = useRef();
const childElementRef = useRef();
const [focusedElement, setFocusedElement] = useState();
useEffect(() => {
const clickEventListener = (event) => {
event.stopPropagation();
setFocusedElement(event.currentTarget);
console.log('click');
console.log(event.target === childElementRef.current);
console.log(event.currentTarget === childElementRef.current);
};
const blurEventListener = (event) => {
event.stopPropagation();
console.log('blur');
console.log(event.target === childElementRef.current);
console.log(event.currentTarget === childElementRef.current);
};
parentElementRef.current.addEventListener('click', clickEventListener);
parentElementRef.current.addEventListener('blur', blurEventListener);
childElementRef.current.addEventListener('click', clickEventListener);
childElementRef.current.addEventListener('blur', blurEventListener);
return () => {
childElementRef.current.removeEventListener('click', clickEventListener);
childElementRef.current.removeEventListener('blur', blurEventListener);
parentElementRef.current.removeEventListener('click', clickEventListener);
parentElementRef.current.removeEventListener('blur', blurEventListener);
};
}, []);
useEffect(() => {
focusedElement?.focus();
}, [focusedElement]);
return (
<div
ref={parentElementRef}
style={{
display: 'flex',
flexDirection: 'column',
width: '100vw',
height: '100vh',
backgroundColor: 'green',
}}
>
<div
ref={childElementRef}
contentEditable={focusedElement === childElementRef.current}
suppressContentEditableWarning
style={{
width: '200px',
height: '200px',
backgroundColor: 'red',
}}
>
Hello world!
</div>
</div>
);
}
And this is a StackBlitz link to try it out:
https://stackblitz.com/edit/vitejs-vite-pibe1s?file=src%2FApp.jsx
If you click on the 'Hello world!' text and then on the green space, you will get this output:
click
true
true
blur
true
true
click
false
false
blur
true
true
If you click on the red square, BUT NOT in the 'Hello world!' text, you get this output:
click
true
true
blur
true
true
click
false
false
If you remove display: 'flex' from the parent element, you will always get the same output no matter where you click on the red box.
I just want to understand this behavior. Why does it even matter if I have display: 'flex' or not in the parent, and when it has it, why does clicking in the text make any difference in how many times the blur event is executed?
Desired behavior:
The code should output this in the console when interacted as specified, which is what I would expect:
click
true
true
blur
true
true
click
false
false
Specific problem or error:
I get this output instead and I'd like to understand why:
click
true
true
blur
true
true
click
false
false
blur
true
true
Shortest code necessary to reproduce the problem:
This is the code I just posted at the beginning of this post.