useRef in React 19

The useRef hook is a useful tool in React for accessing DOM elements and storing mutable values. React 19 introduces a simpler way to work with refs in components.

Note: I'm using JavaScript for the examples in this blog post for simplicity and clarity, but I recommend using TypeScript for your projects.

Basic useRef Usage

Before we check out the new React 19 changes, let's start with a simple example of how we've been using useRef up until now:

import React, { useRef } from "react";

function TextInput() {
  const inputRef = useRef(null);

  function focusInput() {
    if (inputRef.current) {
      inputRef.current.focus();
    }
  }

  return (
    <div>
      <input ref={inputRef} type="text" placeholder="Try focusing me" />
      <button onClick={focusInput}>Focus Input</button>
    </div>
  );
}

In this example, the useRef hook creates a reference to the input element. Think of it as a way to "grab onto" a DOM element directly.


When you click the button, inputRef.current gives us access to the actual input element, allowing us to call browser APIs like focus() on it. The element maintains its state between renders.


This is particularly useful when you need to interact with DOM elements directly, like focusing inputs, playing videos, or measuring element dimensions.

Using refs with Custom Components

If you try to pass a ref directly to your own component like this:

function CustomInput({ placeholder }) {
  return <input placeholder={placeholder} />;
}

function Form() {
  const inputRef = useRef(null);

  // ❌ This won't work.
  return <CustomInput ref={inputRef} />;
}

You'll get an error in the console that might look something like this:

TypeError: Cannot read properties of null

The way we would solve this is by using the forwardRef API:

// CustomInput.js
import React, { forwardRef } from "react";

const CustomInput = forwardRef((props, ref) => (
  <input type="text" ref={ref} {...props} />
));

// Form.js
import React, { useRef } from "react";

function Form() {
  const inputRef = useRef(null);

  function handleFocus() {
    if (inputRef.current) {
      inputRef.current.focus();
    }
  }

  return (
    <form>
      <CustomInput ref={inputRef} placeholder="Enter your name" />
      <button type="button" onClick={handleFocus}>
        Focus Input
      </button>
    </form>
  );
}

The New Way in React 19

React 19 simplifies this by making refs work like any other prop. You can now directly access ref as a prop in your function components without using forwardRef:

// CustomInput.js
function CustomInput({ ref, ...props }) {
  return <input type="text" ref={ref} {...props} />;
}

// Form.js
function Form() {
  const inputRef = useRef(null);

  function handleFocus() {
    inputRef.current?.focus();
  }

  return (
    <form>
      <CustomInput ref={inputRef} placeholder="Enter your name" />
      <button type="button" onClick={handleFocus}>
        Focus Input
      </button>
    </form>
  );
}

This new approach:

  • Eliminates the need for forwardRef
  • Makes refs behave like regular props
  • Reduces boilerplate code

In future versions, forwardRef will be deprecated and eventually removed.

Resources

Feedback

If you have any questions or suggestions about this guide, feel free to reach out: