React. useRef hook
UseRef hook features and use cases
Since the hooks appeared, you have probably gotten “tired” of using useState
and useEffect
in your functional components. At the end of the day, they are probably the most intuitive to use within the React universe.
However, the useRef hook is less common despite its interesting characteristics and because without it we would not be able to implement certain functionalities (something that we will see at the end of this article). Therefore, in this article I want to tell you about its operation and its most interesting use cases.
Let’s go there!
UseRef hook characteristics
The useRef
hook has its origin in the createRef
method that is used in class components and that allowed to create a “reference” (forgive redundancy) to a DOM element created during rendering.
This part is important. In React, the most common thing when we want to modify an element of the DOM is to force a new render by means of a change in the state, that is, we delegate the generation of the DOM to React, which will build the tree based on the properties passed to the elements. We can see it as a case of declarative programming.
However, there are times when we need to modify a DOM element imperatively, for example when we want to make an animation, play a multimedia file or force a “focus” on a field. This is when it is useful to have the direct reference to the DOM element to be able to modify it imperatively.

In the example above, we create a reference in the component’s constructor that we later assign using the input’s ref
property. When the user clicks the button, we directly access the DOM element using this.textInput.current
to invoke its focus()
method.
The functional version of this component using the useRef hook would be:

There are hardly any modifications between one version and another beyond how “clean” the component is when we convert it to functional style.
Forwarding refs
However, this has a very obvious limitation. If we wanted to establish the reference to the input from another component, it would not be worth trying something like this:

That is, we cannot directly forward a reference that is assigned to us from the top element in the component tree. For it to work we need to wrap the component with the React.forwardRef call which allows the wrapped component to pick up a reference that is assigned to it and pass it to its child components:

You can read more about this feature in the official React documentation:
useRef. Storing mutable information
But useRef
is not only a way to declare references to DOM elements but we can also use it to store mutable information. In fact and as Dan Abramov said in the following tweet:
useRef () is basically useState ({current: initialValue}) [0]
This means that we can modify the value of the current
property of the value returned by useRef
at any time:
const value = useRef('foo');value.current = 'bar';
Unlike what happens with the useState
hook that forces us to use the setState
function to modify the value of the state. The important thing here is: modifying the value of the reference by means of the current
property does not produce a new render.
So many times we can see the useRef
hook as the possibility of taking a look at the future. I think this example explains it perfectly:

The key here is that if within the setTimeout
callback we were using the count
variable associated with the useState
hook, what we would be doing is a closure on it. That is, if we press the button 3 times causing 3 effects and therefore 3 timeouts, what we would get on the console would be what we “expected”:
Messages enqued: 1 (valor the count en el instante N-2)
Messages enqued: 2 (valor the count en el instante N-1)
Messages enqued: 3 (valor the count en el instante N)
But if for whatever reason we need to know how many messages are already queued at the moment the callback is resolved (even though we have declared it “in the past”), the mutable value returned by useRef
is the key, since it allows us to escape from the “closure” and get its current value, not the one the variable count
had at the time the effect was declared (and which was “remembered” by the “closure”).
Yes, I know it’s something that can make your head explode at first, that’s why I’m leaving the codesandbox for you to see with your own eyes:
Final thoughts
As you have seen, the useRef
hook is much more useful than we might suppose at first, especially in the latter case since it allows us to avoid some of the restrictions that are given together with the functional components and the “closures” that occur. on the variables at the time we declare effects.
To understand all this in due course I am going to leave you 3 more articles (in addition to as always the fantastic documentation that React has) so you can read more if you want: