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 nullThe 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:
- Email: marcoshaber99@gmail.com
- LinkedIn: Marco Haber
- Github: @marcoshaber99