React: Why focusing children triggers parent's onBlur
The issue
When making a container you may not want to trigger onBlur
on the container when a child is focused, this is really useful in the case of a dropdown menu: you don’t want the menu to disappear when an element within it is clicked.
Intuitively, you may think, that since the children is focused so must be the parent, right? But that is not the case, as only one element at a time may be focused, this makes sense and can be proven by simply tabbing around any web page, you can only select one thing at a time, otherwise you wouldn’t be able to select anything.
So how do we stop onBlur
from triggering? Well, onBlur
should only trigger when you leave the container altogether.
If you select a child of the container and the container’s onBlur
gets triggered, you’re doing something wrong.
The solutions
Try adding tabindex
If the parent element is not an element that can receive focus, such as your ordinary <div></div>
you will need to specify the tabindex
attribute: <div tabindex=1></div>
Wait for the focus
The next solution is relatively simple, what if the browser can’t catch up? Then you’ll need to wait for the focus event, luckily all of this is already documented and summed up here: https://muffinman.io/blog/catching-the-blur-event-on-an-element-and-its-children/
The mousedown event…
If none of the above solutions worked, there’s still hope. In most browsers, the mousedown
event should, theoretically, trigger before the focus event, you can use this to your advantage and check for it when handling onBlur
.
I strongly disagree with this method, if nothing worked for you so far, I suggest you get a duck.
Related StackOverflow answer: https://stackoverflow.com/questions/12092261/prevent-firing-the-blur-event-if-any-one-of-its-children-receives-focus#12092486