Detect whether input element is focused within ReactJS

How can I detect whether an input element such as the following is currently focused within a ReactJS render function?

<input type="text" style={searchBoxStyle} placeholder="Search"></input>   

Upvotes: 124

Views: 212015

Answers (7)

Abhishek E H
Abhishek E H

Reputation: 482

Using functional component you can determine if the current input has focus:

import React from "react";

export default function App() {
  const ref = React.createRef(null);

  const handleMouseOut = (currentRef) => {

    if (document.activeElement === currentRef) {
      console.log("Yesss");
    }
  };
  return (
    <div className="App">
      <input
        type="text"
        ref={ref}
        onMouseOut={() => handleMouseOut(ref.current)}
      />
    </div>
  );
}

Edit Invisible Backdrop

Upvotes: 1

deathfry
deathfry

Reputation: 744

There is a much easier approach with hooks. Make an import:

import React, {useState} from "react";

Define:

const [isMyInputFocused, setIsMyInputFocused] = useState(false);

And in your chosen input just add:

onBlur={() => setIsMyInputFocused(false)}
onFocus={() => setIsMyInputFocused(true)}

And from now on you could access the isMyInputFocused as you wish.

Upvotes: 10

Rasaq Ganiyu
Rasaq Ganiyu

Reputation: 1

***Adjusting answer from @Abhishek E H, there will be a little delay if you use onMouseOut but using onFocus works perfectly fine. Thank you for the inspiration.


import React from "react";

 export default function App() {
   const ref = React.createRef(null);

   const handleMouseOut = (currentRef) => {

if (document.activeElement === currentRef) {
  console.log("Yess");
   }
 };
return (
<div className="App">
  <input
    type="text"
    ref={ref}
    onFocus={() => handleMouseOut(ref.current)}
  />
</div>

); }

Upvotes: 0

David Hellsing
David Hellsing

Reputation: 108480

You can check against document.activeElement as long as the input node is mounted and there is a reference to it:

const searchInput = React.useRef(null)

if (document.activeElement === searchInput.current) {
  // do something
}

return <input type="text" ref={searchInput} />

Another way would be to add event listeners for the focus and blur events inside the input field:

const [focused, setFocused] = React.useState(false)
const onFocus = () => setFocused(true)
const onBlur = () => setFocused(false)

return <input type="text" onFocus={onFocus} onBlur={onBlur} />

Note that this will call a re-render each time the node is focused or blurred (but this is what you want, right?)

Upvotes: 225

Sam
Sam

Reputation: 2331

Depending on what you want to do, you can use onFocus (React 17) or onBlur (React 16) to implement the functionality that you want when these things are in focus.

Upvotes: 0

Rolando Niub&#243;
Rolando Niub&#243;

Reputation: 1215

Using hooks:

First you create and initialize your Reference

const yourElement = useRef(null)

Then You tag your element with the reference you have just created:

<div ref={yourElement}>Im an DOM node</div>

And then, you use this logic as you need to compare if the document.activeElement document property is equal to the DOM node you are referencing to

yourElement.current === document.activeElement

Upvotes: 14

Marcos Abreu
Marcos Abreu

Reputation: 2852

I started with the answer given by David, where he describes two methods, and they both worked for me, but I had concerns about both:

  1. On the first case it uses findDOMNode, what has some disadvantages: at minimum its use is discouraged, and it can easily be implemented in a way that it is considered an anti-pattern; and also it can make the code slower, by bypassing the virtual DOM and working with the DOM directly.

  2. On the second option, create and manage a component state only to find that answer seems too much work, can easily get out of sync, and can cause the component to re-render unnecessarily.

So after trying to explore the issue more, I came up with the following solution:

if (this.props.id === document.activeElement.id) {
  // your code goes here
}

The same comment on David's answer applies:

You should not do this in the render method though, because the input node might not be mounted yet. Use a lifecycle method like componentDidUpdate or componentDidMount.

Advantages:

  • uses the current component properties (which are immutable values)
  • doesn't require state management, and therefore won't cause unnecessary re-rendering
  • doesn't require DOM traversing, so performance should be as good as it gets
  • doesn't require creating a component reference

Requirements:

  • your component should have an id property that is passed to the form element you want to check (which is most likely the case anyway)

Upvotes: 20

Related Questions