Storing values with the useRef hook

Updated 6 November 2024
·
react

React’s useRef hook is most commonly used to store references to DOM elements. But did you know you can also use it to store and update values?

Storing element references with useRef

Before we jump into storing values with useRef, let’s quickly go over the most standard use-case for the useRef hook. It’s most commonly used to store a reference to a DOM element. We do this by creating the ref, and then passing it into the element:

const Component = () => {
    const ref = useRef(null);
    return <div ref={ref}> Hello world</div>;
};

With this reference to the element you can do lots of useful things like:

  • Grabbing an element’s height and width
  • Seeing whether a scrollbar is present
  • Calling focus() on the element at a certain moment

Storing and updating values with useRef

We can also use the useRef hook to store values, which you can later use and change:

const Component = () => {
    const ref = useRef({
        renderCount: 0
    });
 
    // Increase the render count on every re-render
    ref.current.renderCount += 1;
 
    return <>Hello world</>;
}

Note that to change the ref’s value, you will need to change ref.current (and not ref itself!)

useRef vs useState: What’s wrong with useState?

The key difference between useState and useRef is that:

  • If you update the the state value in in useState, your component will re-render
  • If you update the value stored in useRef, nothing will happen

If you don’t need the component to re-render (or you don’t want the component to re-render), useRef may be a good candidate.

What’s the difference between useRef and using a variable?

If you tried initializing a let variable like this:

const Component = () => {
    let renderCount = 0;
    renderCount += 1;
 
    return <>Hello world</>;
}

The renderCount value would keep getting re-initialized each time the component renders, and reset to 0. If you use a ref, the value you store in it will persist between renders of your component.

What about if I define the variable outside of the component?

If you initialize the value outside of your component like this:

let renderCount = 0;
 
const Component = () => {
    renderCount += 1;
    return <>Hello world</>;
}

The renderCount value will be global to all instances of Component. If you change the value, it will affect the value for all the other components you have rendered on your page.

So if you happened to have 10 of these Components on your page (hypothetically speaking), after one render of your app, the renderCount value would already be at 10.

useRef vs createRef

createRef is the API that React provided for refs before hooks came around:

import { createRef } from 'react';
 
class Component extends React.Component() {
    ref = createRef();
 
    render() {
        this.ref.renderCount += 1;
        return <div>Hello world</div>;
    }
}

If you’re using functional components I would recommend using useRef over createRef.

How to use useRef in class components

As useRef is a hook, it will only work with functional components.

With class components, you can use the createRef() example I showed above.

You can also achieve the same thing using a class variable:

class Component extends React.Component() {
    renderCount = 0;
 
    render() {
        this.renderCount += 1;
        return <div>Hello world</div>;
    }
}

Recent posts

Comments