How to Focus an Input with useRef

Use useRef to point at an input element and call focus() on it, so a button or an Effect can move keyboard focus to the field.

5 min read

Focusing an input is an imperative browser action, so declarative rendering alone cannot move the cursor into a field. You need a ref to the input's DOM node and a call to the browser focus method. This article shows how to focus an input from a button click and how to focus it automatically on mount.

Focus from a button click

Create a ref with useRef, attach it to the input, and call focus inside the click handler.

App.jsxApp.jsx
import { useRef } from "react";
 
function SearchForm() {
  const inputRef = useRef(null);
 
  return (
    <>
      <input ref={inputRef} aria-label="Search" />
      <button onClick={() => inputRef.current.focus()}>
        Focus the search
      </button>
    </>
  );
}

Clicking the button places the text cursor inside the field. The ref attribute tells React to put the input's DOM node into inputRef.current, and the handler calls focus on that node. The aria-label gives the field an accessible name so screen readers announce it.

When current becomes available

inputRef.current starts as null. React sets it during the commit phase, after the DOM node has been created and committed to the screen.

This ordering matters. Reading inputRef.current during render returns null on the first render, because the node does not exist yet. Event handlers are safe because they run after the commit. If you need focus at another moment, an Effect is the right place.

Focus automatically on mount

To focus the field as soon as it appears, run the action in an Effect with an empty dependency array.

App.jsxApp.jsx
import { useRef, useEffect } from "react";
 
function LoginForm() {
  const emailRef = useRef(null);
 
  useEffect(() => {
    emailRef.current.focus();
  }, []);
 
  return <input ref={emailRef} type="email" aria-label="Email" />;
}

When the form mounts, React runs the Effect after commit and the field receives focus. The empty array makes the Effect run once, so focus is not stolen again on later re-renders. Focus is a one-time command, not a subscription, so this Effect needs no cleanup.

Prefer autoFocus when it is enough

For the mount-time case, React has a declarative shortcut.

App.jsxApp.jsx
<input autoFocus placeholder="Type a query" />

The autoFocus attribute tells the browser to focus the input when the page loads, with no ref and no Effect. Use it for a single field that should always start focused. Use the ref approach when focus happens on demand, like a button click, or when the decision depends on other data.

Focus through a custom component

If the input lives inside a wrapper component, pass the ref down as a prop. In current React, ref is an ordinary prop on function components.

App.jsxApp.jsx
function SearchInput({ ref }) {
  return <input ref={ref} />;
}

The wrapper forwards the ref prop straight to the real input, so no forwardRef call is needed. The parent then uses it like any other component.

App.jsxApp.jsx
import { useRef } from "react";
 
function SearchForm() {
  const inputRef = useRef(null);
 
  return (
    <>
      <SearchInput ref={inputRef} />
      <button onClick={() => inputRef.current.focus()}>Focus</button>
    </>
  );
}

The parent's inputRef now points to the input inside SearchInput. For cases where you want to expose only a limited set of methods, passing refs between components covers the details.

What to learn next

Focus is one of several DOM actions refs unlock. Continue with accessing and measuring DOM elements in React.

Rune AI

Rune AI

Key Insights

  • Pass the ref object to the input with ref={inputRef}.
  • React fills inputRef.current during the commit phase, after the DOM node exists.
  • Call inputRef.current.focus() from an event handler or Effect, never during render.
  • Use the autoFocus attribute for focus when the page first loads.
  • Give the input a label so the focused field announces its purpose.
RunePowered by Rune AI

Frequently Asked Questions

Why is inputRef.current null on the first render?

React attaches refs during the commit phase, after the DOM node exists. On the first render the node is not created yet, so current starts as null.

Can I focus an input without useRef?

Yes. For focus on mount, the autoFocus attribute on the input does it declaratively with no ref or Effect.

Does focusing an input need an Effect cleanup?

No. Focus is a one-time browser command, not a subscription, so there is nothing to clean up.

Conclusion

Attach a ref to the input, then call focus() on ref.current from an event handler or Effect. Use autoFocus for the simple mount-time case and save useRef for focus that must happen on demand or in response to another component.