useRef Explained

Sam Dent
The Startup
Published in
5 min readDec 13, 2020

This an overview of useRef for those new to React and hooks and assumes a basic understanding of what the DOM is.

useRef is a hook that can be tricky to get to grips with since it’s one that you might only meet once in a blue moon. That’s by design.

But understanding what it is and what it does means gaining a much better understanding of how React works overall, and at the end of the day isn’t that what we all want in our heart of hearts? ❣️

useRef say what!?

Ok I promise this is an article for newer react users but this next bit is heavy, bare with me! 🐻

First I’ll give a high level overview of what useRef is, then I’ll try and explain things with more context so you have an understanding of what useRef is doing and why you’d ever want to use it.

Ok here goes…

useRef is a hook which returns an object with a current property set to the value passed to the hook.

For instance this:

 const numberRef = useRef(0);
// numberRef is initialised as an object with a current property

Would return an object like so:

 {current: 0};
// numberRef.current holds the value 0

This object is mutable so the current property can be changed. Importantly this object exists outside of React’s render cycle, so the value persists throughout a components lifecycle.

It also provides a way for developers to interact directly with DOM nodes, outside of React’s management of the Virtual DOM. React describes this an ‘escape hatch’.

We can use the ref attribute of React elements to set the “current” property to be the actual DOM node the element is rendered to. This way we can use the reference for old school DOM manipulation adding event listeners etc.

const divRef = useRef();
/* divRef is initialised with current property set to 'undefined' because we didn’t give a value to the hook.*/
...const MyComponent = (props) => {
return <div ref={divRef}> A Div! </div>;
};
.../* by passing divRef to the ref={} attribute, when the component is mounted to the DOM the divRef.current property gets set to the actual DOM node, eg. "<div>A Div!</div>" */

WOAH

If that sounded like gibberish that’s because we’re wading into the world of React jargon.

Let’s back up a little now and get some wider context.

React, Rendering, and the DOM

React is a framework that uses a layer of abstraction away from the original browser DOM API (The Document Object Model that describes web pages as a tree of nested objects).

Using vanilla JavaScript we would have to go through the cycle of targeting and updating the DOM ourselves (Using document.querySelector() etc.).

But everytime we change a DOM node in this way, the whole DOM tree needs to be re-rendered. Changing inner text on that wee tiny <p> tag means having to re-render the whole Document!

React however, works with a Virtual DOM. It keeps a track of changes in it’s own Virtual DOM before ‘mounting’ to the old school DOM in the way it deems most efficient.

By maintaining a virtual DOM React can figure out how to update only what is necessary, on a component by component basis.

It manages the DOM so we don’t have to!

When we trigger a state change in a component (calling setState()or the likes), only the components that need to change are changed, or re-rendered. They get mounted to the old school DOM fresh and new but with the state values updated. That is the basics of the React render cycle.

So in a nutshell, once upon a time poor developers had to spend time manipulating the DOM themselves, each time something in the DOM changed the WHOLE THING was changed, this made the DOM powerful but slow.

Then one day React came along and said “You’re a busy developer, why don’t you just tell us what’s important and we’ll manage that DOM stuff for you”

— Boom abstracted!

Well gee thanks!

But... what if we want to use React AND want, or really (like really, really) need, to change the old school DOM ourselves?

That’s where refs come in to the story. --pheww finally!!

useRef again

Back to useRef, levelled up with our new contextual knowledge!

There are two main uses of the useRef hook.

The first being for interacting with the browser DOM directly to make changes, rather than letting React manage things through the virtual DOM. This can be useful for integrating libraries written for vanilla js apps with your React app, I’ve seen this done with the D3 data visualisation library a few times for instance.

BUT this comes with heavy caveats from React about its use. Since the magic of React is that abstraction away from the DOM, we WANT React to take care of the DOM for us.

If we start micromanaging and changing things in the DOM directly then React may no longer behave as expected.

Still every good vehicle comes with a s̶e̶l̶f̶-̶d̶e̶s̶t̶r̶u̶c̶t̶ ̶b̶u̶t̶t̶o̶n escape hatch and that’s how React encourages us to think about refs.

The second use you might see is for creating an object with values which persist between renders.

Each time a React component is rendered it is done so with fresh local variables, any values that were updated, that aren’t kept in state, get reset.

useRef creates an object that will hold on to values even when state changes and the component re-renders. This makes it very useful for doing things like tracking the previous state or counting how many times a state changes.

This use is sort of like using state but without the UI implications. For when you want to track a value that might change but isn’t going to change how your app looks at all.

Examples

I hope that things are a little clearer now but if you’re anything like me it will take a little more exposure before anything sinks in. With that in mind I’d like to offer an example.

  • To see useRef provide a way to track the previous state of a component visit this article.

Hopefully this has given you a better understanding of the useRef hook, it’s defo one that can seem confusing with out the right context.

It’s use is an area for debate amongst dev teams. Some devs throw refs around willy nilly and others get all dark and serious at the mention.

Just know that most of the time you should be aiming for a React friendly way to manage your UI, and as such you should probably be looking to use something other than useRef.

That said rules are made to be broken so experiment, have fun, learn!

--

--

Sam Dent
The Startup

Adventuring in the world of software development.