How to use forwardRef in React

Typically in React we want to keep logic within components and preserve unidirectional data flow. However that’s not always possible, and sometimes we need to access the DOM element itself. This is where refs come in.

In this article, we’ll cover a general overview of refs, how to create them, and attaching them to custom components using forwardRef. We will also use the useRef() hook rather than the older createRef() method. Ready? Let’s dive into it.

What are refs?

Refs provide a way to access and interact with the DOM or React elements directly. They allow you to perform a variety of actions such as focusing, trigging animations, calculating size or position, or interacting with third-party libraries that need direct access to DOM elements.

To create a ref, we call the useRef() hook within a component. This creates a plain JavaScript object that holds the element in the current property. We can then attach it to a component to have access to it later.

We could use vanilla JavaScript to access components directly, but this is not recommended. It is also bad practice in React to directly access the DOM.

What is forwardRef?

React provides the higher-order component forwardRef to pass a ref from a parent component to a child component. It accepts a component as an argument and returns a new component.

forwardRef is useful when you need to access or manipulate custom child components. Typically, passing ref as a prop will not work and will result in an error. The ref will point to the wrapper component rather than the element itself, resulting in the ref being null. See the console in example below.

At Gravity Forms we use forwardRef for our custom components. We build our components mainly for our own apps, but we also have a community of developers who extend our code and use it for their own plugins. Because of this, we build them to be flexible and allow our components to handle ref forwarding.

Passing the ref

Now that we understand what ref and forwardRef are, we are now ready to use them.

First we’ll create a custom input component. We won’t worry too much about the complexities of the input, we’ll just pass the props straight through to the input element. Then we’ll wrap the input component in forwardRef and add ref as a second argument to the functional component.

Next, let’s create an App component that uses the custom input component. We will also create a ref by calling useRef() within the App component and pass it to the input. Finally, we’ll add a button element to the App component that focuses on the input when it is clicked.

Putting it all together, it’ll look something like below. When we click on the button, it grabs the ref of the input component and focuses on it.

This is a very simple example, but we can use this same pattern to do more complex DOM manipulations.

When not to use refs

Refs are a powerful tool. It allows developers to access React DOM elements directly and interact with them. However, there are some situations where refs are likely not the right solution. This is not an exhaustive list, but illustrate a general pattern for data flow.

Manipulating state

Refs are not ideal for managing UI state within React components. Rather, use the useState() hook within the component or a centralized state management library such as Redux to manage app state. This supports the unidirectional data flow concept of React and allows data flow to be more predictable and maintainable.

Styling and CSS

Instead of styling components through refs, it is better to use one of the various libraries for styling components, such as CSS-in-JS or CSS modules. These solutions allow for a more modular and maintainable approach to building components and apps.

Data fetching and side effects

Refs should not be used to handle data fetching or side effects in components. React provides the useEffect() hook to manage data fetching, subscriptions, and other side effects. Using this hook ensures proper synchronization and cleanup of resources within the component.

Wrapping it up

Refs expand the possibilities for developing in React. However, they should be used carefully. Combining refs with forwardRef allows for more control over custom components, providing yet another tool for developers to use. Now that you know how to use it, go ahead and incorporate forwardRef into your projects and take your components to the next level!