Quick Tip — Using Callback Refs in React
Tags: ref, react, usecallback, useeffect
Published: 2023-11-13 09:31:46

---
title: Quick Tip — Using Callback Refs in React
published: true
date: 2023-11-13 09:24:09 UTC
tags: ref,react,usecallback,useeffect
canonical_url: https://gilfink.medium.com/quick-tip-using-callback-refs-in-react-2785ae5efb21
---

### Quick Tip — Using Callback Refs in React

![](https://cdn-images-1.medium.com/max/1024/1*-KpsjMpEgajZ9dVreK7bUQ.png)
_The Post Code in Code Sandbox_

One of the usages I see a lot with **useEffect** in React code is to run some JavaScript code on an element reference which is stored as ref as soon as this element is mounted. For example, when an element is mounted, animate it’s content using [Web Animation API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Animations_API/Using_the_Web_Animations_API).

The following code is doing exactly that:

{% gist https://gist.github.com/gilf/4b918cde4aa40627171625dc6de51fee %}

In the code above, you set the ref to the heading element and when the component is mounted, it’s animating the heading with some premade animation.

That is easy, so why should you bother reading this post at all?   
Because there is a better alternative to do exactly the same thing but without **useEffect** and **useRef ** hooks.

The **ref** attribute is expecting that you will set it with one of the following types:

```
RefCallback<T> | RefObject<T> | null
```

A **RefCallback** is just a function that accepts the element node and returns void. In a matter of fact, whenever you use **RefObject** , it’s just a syntactic sugar to set the reference on the element to the **current** accessor of the **useRef** created reference. The following code is what is going to happen when you set a **ref** like in the first code block in this post:

```
<h1
  ref={(node) => {
    ref.current = node;
  }}
/>
```

The **RefCallback** function is going to run after the component is mounted, re-rendered or unmounted.

Now, packed with this knowledge, how you can refactor the above code and stop using **useEffect** and **useRef** combination?

The following code will do exactly that:

{% gist https://gist.github.com/gilf/cd3d6a26daf6c2de1b48bbf08694fdcc.js %}

Let’s try to understand what is going on. In the code, you use the **useCallback** function with an empty dependency array to wrap the callback ref function. This will make sure that React runtime will run this function only on mount and that is it. No need to use the **useRef** or **useEffect** hook and you achieve the same functionality. You gain two adeed bonueses when you use callback ref. The first one is that you don’t get double rendering in development mode like you will get when you use **useEffect**. The second bonus is that in the case of using **forwardRef** and conditional rendering, the callback **ref** code will stay stable and work while the **useEffect** code might not work as expected if the element isn’t rendered due to the conditional rendering.

If you want to look at the provided code and see how it works, you can play with the previous code in this sandbox:

<iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fcodesandbox.io%2Fembed%2Fmuddy-currying-73mvyz%3Ffontsize%3D14%26hidenavigation%3D1%26theme%3Ddark&amp;display_name=CodeSandbox&amp;url=https%3A%2F%2Fcodesandbox.io%2Fembed%2Fmuddy-currying-73mvyz%3Ffontsize%3D14%26hidenavigation%3D1%26theme%3Ddark&amp;image=https%3A%2F%2Fcodesandbox.io%2Fapi%2Fv1%2Fsandboxes%2F73mvyz%2Fscreenshot.png&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=codesandbox" width="1000" height="500" frameborder="0" scrolling="no"><a href="https://medium.com/media/9c583e21c4c620c5e9138e5c7bb3d6be/href">https://medium.com/media/9c583e21c4c620c5e9138e5c7bb3d6be/href</a></iframe>

For further reading about callback refs, you can look at React documentation: [https://legacy.reactjs.org/docs/refs-and-the-dom.html#callback-refs](https://legacy.reactjs.org/docs/refs-and-the-dom.html#callback-refs)