skip to Main Content

I have a requirement to display an input field and focus the element on click of a button my code snippet looks like this

import { useState, useRef } from 'react';

function App() {
  const inputRef = useRef(null);
  const [enableSearch,setEnableSearch]=useState(false);

  const handleClick= () => {
    setEnableSearch(!enableSearch)
    inputRef.current.focus();
  }

  return (
    <div >
      {enableSearch&&<input ref={inputRef}/>}
      <button  onClick={handleClick}>show input</button>
    </div>
  );
}

export default App;

I am not able to get the cursor focus on the input when enableSearch condition is used what is wrong in this implementation?

3

Answers


  1. Updating state in React is asynchronous, so react will wait until all the code in the event handler has run before processing the state update. (docs)

    That’s why when you’re trying to focus on the input, it will throw an error since the input doesn’t exist yet.

    You could use useEffect to change focus when the enableSearch value changes to true

    export default function App() {
      const inputRef = useRef(null);
      const [enableSearch, setEnableSearch] = useState(false);
    
      useEffect(() => {
        if (enableSearch) {
          inputRef.current?.focus();
        }
      }, [enableSearch])
    
      const handleClick = () => {
        setEnableSearch(!enableSearch);
      };
    
      return (
        <div>
          {enableSearch && <input ref={inputRef} />}
          <button onClick={handleClick}>show input</button>
        </div>
      );
    }
    
    Login or Signup to reply.
  2. In your case, input field is not rendered because you have added conditional rendering. When you click on button , you changed value of enableSearch. As useState hook updater method behave like async so it take may take few time and on next line you added inputRef.current.focus(). Again, may be your input is not rendered yet therefore it not able to fine inputRef that is null and therefore you focus was not working.

    Here is updated code snippet to add focus on button click

    import { useEffect, useRef, useState } from "react";
    function App() {
      const inputRef = useRef(null);
      const [enableSearch, setEnableSearch] = useState(false);
    
      const handleClick = () => {
        setEnableSearch(!enableSearch);
      };
    
      useEffect(() => {
        if (enableSearch) {
          inputRef.current?.focus();
        }
      }, [enableSearch]);
      return (
        <div>
          {enableSearch && <input ref={inputRef} />}
          <button onClick={handleClick}>show input</button>
        </div>
      );
    }
    export default App;
    
    
    Login or Signup to reply.
  3. if that’s all what you need that ref for, then you can do this:

    import { useReducer } from "react";
    
    const autoFocus = input => input?.focus();
    
    function App() {
      const [enableSearch, toggleSearchInput] = useReducer(v => !v, false);
    
      return (
        <div >
          {enableSearch && <input ref={autoFocus} />}
          <button onClick={toggleSearchInput}>show input</button>
        </div>
      );
    }
    
    export default App;
    

    https://reactjs.org/docs/refs-and-the-dom.html#callback-refs

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search