Skip to content
Advertisement

React: Fire a function when the element is blurred

I’m trying to fire a function when an element has loses focus, but it appears the blur event is not being recognized in my React app. I’m unclear on what I’m missing. The following snippet is just above the return method within my component.

My div carries the ref {infoWindow}. At the moment, the console.log is not outputting anything when I click inside the div window and then out.

const infoWindow = useRef<HTMLDivElement>(null);
if (infoWindow.current) {
  infoWindow.current.addEventListener('blur', (event) => {
    console.log(`We've been blurred`);
  });
}

Advertisement

Answer

This is not how you introduce side effects in React, adding an event listener to an element is a side effect, and side effects should be created inside a useEffect.

Here is the problem with your code

const infoWindow = useRef<HTMLDivElement>(null);
// assume your component gets rendered once - at the initial render the component is not mounted in dom yet
// then infoWindow.current is null, and an event listener will not be added. This is what is probably happening with you.
// assume your component is rendered 1000 times, then you will add 999 event listeners, which is definitely not what you want
if (infoWindow.current) {
  infoWindow.current.addEventListener('blur', (event) => {
    console.log(`We've been blurred`);
  });
}

The solution is to use useEffect

useEffect(() => {
  if (infoWindow.current) {
     const handler = (event) => {
       console.log(`We've been blurred`);
     }
     // notice that i get a reference to the element here, so i can safely use it in the clean function
     const element = infoWindow.current
     element.addEventListener('blur', handler);
     // this is a clean function that will be called to clear the side effects you just introduced
     return () => element.removeEventListener('blur', handler);

  }


}, [])

EDIT What is mentioned above is correct, but you also have another problem, div elements do not receive focus events by default, and so wont blur. If you want an element to blur, and focus, then add tabIndex to it, so on your div do

<div tabIndex={0}>...</div>
User contributions licensed under: CC BY-SA
10 People found this is helpful
Advertisement