Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
onBlur for entire react element
function OnBlurComponent({ onBlur }) {
const handleBlur = (e) => {
const currentTarget = e.currentTarget;
// Check the newly focused element in the next tick of the event loop
setTimeout(() => {
// Check if the new activeElement is a child of the original container
if (!currentTarget.contains(document.activeElement)) {
// You can invoke a callback or add custom logic here
onBlur();
}
}, 0);
};
return (
<div tabIndex="1" onBlur={onBlur}>
Hello <input type="text" value="world" />
</div>
);
}
@peterbe

This comment has been minimized.

Copy link

peterbe commented Oct 20, 2015

Works great!

@djskinner

This comment has been minimized.

Copy link

djskinner commented May 12, 2016

Why is the setTimeout required?

@djskinner

This comment has been minimized.

Copy link

djskinner commented May 12, 2016

For anyone else who is wondering, this answer gives a good explanation of why it is necessary. Thanks for the snippet!

@neaumusic

This comment has been minimized.

Copy link

neaumusic commented Feb 16, 2017

This doesn't seem to work on mac, since document.activeElement is body unless it's an element (input) that can receive keystrokes

The solution for me was to use onMouseDown, which fires before onBlur (click and presumable onMouseUp fire afterwards)
Tested this on iPhone and onMouseDown triggers

@nickbouton

This comment has been minimized.

Copy link

nickbouton commented Feb 19, 2017

Works fine on Chrome/OS X for me, thanks for this @pstoica.

@ericbeijer

This comment has been minimized.

Copy link

ericbeijer commented May 30, 2017

Thanks, works great!

@shanielh

This comment has been minimized.

Copy link

shanielh commented Jun 5, 2017

Thanks!

@mcroba

This comment has been minimized.

Copy link

mcroba commented Aug 21, 2017

@neaumusic you might have forgotten to add the tabIndex on the div

@bmancini42

This comment has been minimized.

Copy link

bmancini42 commented Aug 25, 2017

This is great! Thanks for sharing

@abobwhite

This comment has been minimized.

Copy link

abobwhite commented Sep 1, 2017

Worked great for me! Thanks!

@emirdeliz

This comment has been minimized.

Copy link

emirdeliz commented Sep 27, 2017

Thanks, works great!

@vikamirror

This comment has been minimized.

Copy link

vikamirror commented Apr 3, 2018

Thank you sooooo much! This is just what I needed

@AlexanderLyon

This comment has been minimized.

Copy link

AlexanderLyon commented Apr 13, 2018

Exactly what I was looking for thank you!

@yunay

This comment has been minimized.

Copy link

yunay commented May 10, 2018

I just had this warning when I tried this:
Warning: This synthetic event is reused for performance reasons. If you're seeing this, you're accessing the method currentTarget on a released/nullified synthetic event. This is a no-op function. If you must keep the original synthetic event around, use event.persist(). See https://fb.me/react-event-pooling for more information.

@Mrwaite

This comment has been minimized.

Copy link

Mrwaite commented Aug 15, 2018

Thanks, solved the problem that has been bothering me for a long time.

@mockey-jockey

This comment has been minimized.

Copy link

mockey-jockey commented Sep 12, 2018

Good mind ....thanks a lot you saved me more time..

@blackjacques

This comment has been minimized.

Copy link

blackjacques commented Sep 20, 2018

Awesome! Surprising that we still need such a kluge in 2018!

@aeolusheath

This comment has been minimized.

Copy link

aeolusheath commented Nov 7, 2018

omg !! serveral years later , it still works!!! big thanks

@oreporan

This comment has been minimized.

Copy link

oreporan commented Nov 12, 2018

halleluja!

@jason90929

This comment has been minimized.

Copy link

jason90929 commented Mar 25, 2019

My code works! But I still don't know why

@shawnhutchins

This comment has been minimized.

Copy link

shawnhutchins commented Jun 3, 2019

Awesome! Thanks!

@Iam-Locy

This comment has been minimized.

Copy link

Iam-Locy commented Mar 1, 2020

@neaumusic Thank you, it helped a lot.

@bchoddny

This comment has been minimized.

Copy link

bchoddny commented Mar 14, 2020

Any reason, why the onblur event is on div, instead of on input element? Does it gives any advantage of placing blur event handler on one over the other?
Why would we require a set timeout event?

Thanks.

@pstoica

This comment has been minimized.

Copy link
Owner Author

pstoica commented Mar 14, 2020

@bchoddny:

  • onBlur bubbles up; put it on the outermost element needed. The input is there to show you can still use children with their own onBlur.
  • setTimeout(fn, 0) runs afterwards in the event loop so that document.activeElement refers to the newly focused element. If it's a child, we're still in the container element.
@IvanNazarov

This comment has been minimized.

Copy link

IvanNazarov commented Mar 24, 2020

Thanks! You save my day!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.