Learning About The React useRef Hook And Mutable Values

While less often discussed, the useRef Hook deserves covering because a time will come when it's the right solution to reach for; here, we'll talk about how useRef's "mutable" value property can be useful.

Project Source Code

Get the project source code below, and follow along with the lesson material.

Download Project Source Code

To set up the project on your local machine, please follow the directions provided in the README.md file. If you run into any issues with running the project source code, then feel free to reach out to the author in the course's Discord channel.

This lesson preview is part of the The newline Guide to Modernizing an Enterprise React App course and can be unlocked immediately with a \newline Pro subscription or a single-time purchase. Already have access to this course? Log in here.

This video is available to students only
Unlock This Course

Get unlimited access to The newline Guide to Modernizing an Enterprise React App, plus 70+ \newline books, guides and courses with the \newline Pro subscription.

Thumbnail for the \newline course The newline Guide to Modernizing an Enterprise React App
  • [00:00 - 00:16] If you've written React code before, you may already be familiar with React's refs. In the React of yesteryear, refs provided a way to access DOM nodes or React elements where you needed to imperatively modify a child outside of the typical flow.

    [00:17 - 00:38] Reasons for using refs might include situations like managing focus, text selection, or media playback, triggering imperative animations, or integrating with third-party DOM libraries. Generally, refs have been thought of as an escape hatch, and the consensus was that reaching for refs often might indicate that state should be owned somewhere else in the component hierarchy.

    [00:39 - 00:59] With the release of hooks, however, use ref got an update that made it easier to use, and I find it a lot more useful today than ever before. Not only can we use use ref to access DOM elements directly, but we can also use it to hold mutable state that won't trigger a component re-render, but will persist the values while the component is mounted.

    [01:00 - 01:13] Here, we'll explore the usefulness of use ref for those instances when we need to direct a React component on how to handle a DOM element. One more note on imperative versus declarative programming.

    [01:14 - 01:30] Whenever possible, let React handle the state of the app and the how of each component, also known as declarative handling. When the situation calls for us to handle the how, like focusing on a particular DOM element once it's been rendered, refs are the way to do so.

    [01:31 - 01:38] That is what's known as imperative handling. Here is our sample use ref code, also in code sandbox.

    [01:39 - 01:54] This example shows two common use case scenarios for the use ref hook, using it to focus on input, and using it to evaluate the inputs new value compared to its old value. The first thing that we will look at is how to use use ref to focus on an input .

    [01:55 - 02:12] The first thing that you'll see when the example code loads is a button titled focus the input. Click it and you'll notice a cursor appears in the input box, and then you can start typing numbers or use the arrow keys to adjust the number up and down.

    [02:13 - 02:25] So we click it, we go up, and suddenly we see the new rate one is higher than the old one. Go up again and two, go down, and now we're back to rate one.

    [02:26 - 02:36] So before we look at the code that's causing this focus on the input box, let's talk about use ref in general, and the code will make more sense afterwards. So how does use ref work?

    [02:37 - 02:49] Use ref returns a mutable ref object whose dot current property is initialized to the past argument. You might think of it sort of like a box holding that value in its dot current property.

    [02:50 - 02:59] A mutable value is any value that's liable to change. It's handy for keeping any mutable value around similar to how you use instance fields in classes.

    [03:00 - 03:14] The use ref hook operates similarly to how you can pass a ref object in react like so. So you would use this my ref to focus particularly on this div in the DOM.

    [03:15 - 03:24] So react will set its dot current property to the corresponding DOM node whenever that node changes. The returned object will then persist for the full lifetime of the component.

    [03:25 - 03:40] And this works because use ref creates a plain JavaScript object. The only difference between use ref and creating your own object with the value of current is that use ref will give you the same ref object on every render.

    [03:41 - 03:55] And keep in mind that use ref does not notify you when its content changes. Mutating the dot current property doesn't cause a re-render the way it would if you mutated something from a use state variable.

    [03:56 - 04:13] So now that we've talked a bit about the mechanics of use ref, let's take a look at that first example again. So when we start to look at our use ref code, the very first variable declaration you'll see inside of our app component is for ref and its initial value is set to null right here.

    [04:14 - 04:34] If you needed to point the ref to a state variable or set it equal to a string or a number that's totally valid and you'll see that when we discuss our second example, but for this one, everything is null and that's good. So just like with use state and use effect, we can pull out use ref from react and then set it right here.

    [04:35 - 04:52] And then inside of our actual JSX, further down the page, we see that we have this input. And that is where we're referencing this input ref and saying, hey, this input should be focused on.

    [04:53 - 05:08] So that variable of input ref is attached to the input component to find in our JSX. And when button is clicked right here, it's on click function of focus input focuses that input ref's current property right up here.

    [05:09 - 05:24] We're imperatively telling the react component to focus on the input that we've attached to input ref in the component. A more common use case might be the same functionality of focusing on an input in the DOM, but on component load with the help of a use effect.

    [05:25 - 05:41] But for illustrative purposes, the on click function triggers the focus on this element instead so you can see it more easily. And even though this example may seem a little trite, it's actually pretty common for forms or other inputs that you might have in your app that you'd like to automatically target.

    [05:42 - 05:52] So it's easier for users to get things done as soon as they land on the page. Okay, so that example is not too far afield from how you might use a ref in a traditional class component.

    [05:53 - 06:04] But let's look at another way that the use ref hook can be utilized now in functional components. And that is using use ref to store values that shouldn't trigger re-renders of the component.

    [06:05 - 06:16] So a unique way to implement a use ref hook is to use it to store values instead of DOM references. Personally, I've done this quite a bit in the large applications that I work on .

    [06:17 - 06:40] These values can either be a state that doesn't need to change too often or a state that should change as frequently as possible but should not trigger full re-rendering of the component for one reason or another. So in that same example, the first ref defined is used to put the focus on the input, but the second ref is defined to compare the input's current value to its previous value and display a message.

    [06:41 - 06:48] If that value is higher or lower than it was previously in the DOM. So here is the code that we want to pay attention to now.

    [06:49 - 07:09] We still have our input ref, but we also have our number ref and our number diff. And down here inside of our application a little bit further down, we have some new variables, a new function called calc new diff, a use effect that keeps track of the number.

    [07:10 - 07:22] And then our actual code that renders out if it's higher or lower. So for this code, first a number state variable is defined right up here.

    [07:23 - 07:30] Number, set number. And a number ref is created to keep track of numbers value right there.

    [07:31 - 07:41] And you can see that our initial value is now number instead of null. So if you were to check right now, number ref.current equals zero in the DOM.

    [07:42 - 07:59] And you can just type a console log of number ref.current inside of the use effect function right here to see for yourself. So once the user starts entering numbers into the input using either the keypad arrows or manually typing them in, the calc new diff function will run each time an action is taken.

    [08:00 - 08:12] Right here. Then because numbers value has been updated and the use effect is watching for that value to change its dependency array, the use effect runs.

    [08:13 - 08:22] Depending on what the number diff state gets set to, it displays the appropriate message in the DOM. So this use effect is where the number ref comes into play.

    [08:23 - 08:48] Inside of use effect, the local variable of old number is set equal to number ref.current because it still retains the previous value for number, even though the state variable number itself has been updated via the input. Once again, I encourage you to add some console logs to this example for old number and number to see how state gets updated, but the ref does not, at least not yet.

    [08:49 - 09:04] So in this way, the use effect can compare the current value of number and the previous value assigned to number and preserved in the number ref.current. Based on which value is greater, display a message in the DOM indicating if the new value is higher or lower than the last value.

    [09:05 - 09:25] And finally, before the use effect is complete, the number ref.currents value is updated to reflect the current value of number so that when the effect is triggered in the future, it can accurately compare values. Although use ref's current value is mutable, unless we updated ourselves, it won't change over the life of the component, re-render, or no.

    [09:26 - 09:34] This is important to remember. Use ref is one of those less discussed hooks on average, but there are many situations where it can really fit the bill.

    [09:35 - 09:42] So let me give you a real world example of use ref. Once again, you might be thinking, why would I ever need this in a real app?

    [09:43 - 09:53] But actually, there are a lot of scenarios where this makes sense. Here's one. In the app that I work on, users can change which department they 're currently viewing products for.

    [09:54 - 10:17] Each time they open a modal, they can switch the departments, and when that happens, the app needs to go out and refetch new data, displaying the products that are part of that selected department. My team uses use ref variables to keep track of the previous department so that if it's changed and the new department value differs from the previous one, the ABI call to fetch data will be triggered.

    [10:18 - 10:35] Of course, there's more than one way that this same thing could be accomplished using React, but that is one example, at least, of use ref at work. Great. So we're more than halfway through the lessons for this module, introducing you to the most common React hooks you will encounter throughout this course and when using hooks in general.

    [10:36 - 10:46] Next up, the use context hook. This one was a true game changer for me once I understood how to use it properly. I'm really excited to introduce it to you too.