Check out a free preview of the full Intermediate React, v5 course

The "useRef" Lesson is part of the full, Intermediate React, v5 course featured in this preview video. Here's what you'd learn in this lesson:

Brian introduces the useRef hook which can store references to DOM elements. This way the component can guarantee the same element is referenced during any re-render cycles. Combining useRef with the memo method will eliminate re-rendering and increase performance for expensive components.

Preview
Close

Transcript from the "useRef" Lesson

[00:00:00]
>> We are just gonna go look at individual hooks. And we're gonna do this for the hooks that I did not cover and complete intro React either at all or very well. I used to cover literally every hook that React puts out. And it eventually got to the point where they're putting out hooks now where I just don't think you're ever going to use them, period.

[00:00:18]
Therefore I don't think it's worth the brain matter to store them, right? So this is not going to be every hook possible but it's all the ones that I conceivably could see an app developer wanting to use at some point. So let's hop into hooks in depth and useRef.

[00:00:37]
So for this we are going to be using StackBlitz. StackBlitz is just like CodePen or CodeSandbox or any one of those things. My favorite thing about stackblitzing though is notice I'm actually running VITE directly in the browser, which you can't do with other ones, right? StackBlitz has a thing called a web container, which basically is running node.js inside of your browser, very impressive technology.

[00:01:05]
So we're gonna do that. So, here's my suggestion to you. I'm going to suggest that you hop directly over to StackBlitz, and I'm gonna suggest that you, yourself, make an account on StackBlitz. I'm not connected to StackBlitz in any way, so I have no reason to encourage you otherwise.

[00:01:26]
Then to fork this, and then you can actually just work on your own copy of this and save it. We're actually not gonna be writing a ton of code on this. We are mostly just going to be exploring all the various different usecases of hooks So just to get you familiar with this project, we have up here a little chooser of all the various different ones.

[00:01:53]
There's also a little homepage where you can choose which one you wanna focus on. First, we are going to go on to useRef first. So, useRef allows you to have a container so that you can have the same value between renders, right? So every time that I run this UseRefMemo component, and we'll talk about memo here in just a second.

[00:02:26]
But for now just focus on this useRef hook. So, the render target here is exactly the DOM element that I'm going to be rendering into. So in this particular case I have down here this ref as this div being the render target. Now, if you give it a ref which is a React thing, not a damn DOM thing, it's going to store this particular div into the render target.

[00:02:56]
I want this because I'm going to be rendering into it, right? So this is a three.js application, the three.js and React don't necessarily play well together, right? They're not made to go together. I'm using a third party library inside of React that is not a React library. There probably is like a three.js React connector.

[00:03:14]
If you needed to do this with something like jQuery, or maybe you have like a React application rendering an Ember application, it's not unheard of. It's messy, but it's possible, right? So I put this renderTarget onto this ref. And now whenever I refer to this renderTarget, so renderTarget.current.appendChild.

[00:03:34]
So I'm actually using the direct DOM node to insert the three.js application. That's what ref allows you to do, allows you to do, allows you to grab hold of specific DOM nodes. And then that's just one usecase for refs. But probably the most common one, which is like, I need a specific DOM element.

[00:03:56]
Cuz the other thing that you could try and do, if I say like ID equals blah, and then I try and query the DOM for ID equals blah. I'm not guaranteed that that specific same DOM element is going to be the same one that I grabbed if I try and query the DOM for it.

[00:04:11]
Because React reserves the right to create and destroy any element at any time. So the only way that you can guarantee that you're getting a hold of exactly the DOM element that you want is with a ref. I'll say that 90% of the usecase for refs is referring directly to the dom, right?

[00:04:30]
Referring to something that exists in the DOM and you wanna keep ahold of that. But it's just a container, right? So notice I'm saying renderTarget.current, renderTarget is just, it's an object that has exactly one property exposed, which is current. So the reason why they do this because then you can have that object and you can refer to the same thing in that current container.

[00:04:51]
I could totally do like, const otherRef = useRef. And otherRef.current is assigned blah, right, it's just like an object. So now I have this object here, well, it's maybe even more, it's const otherObject. Now at any, it equals empty object here. If I was just saying, If I was just creating an object in here, insideObject = blah.

[00:05:51]
This object is getting created and destroyed every single render cycle, right, every single time. Whereas otherRef.current, this is surviving between various render cycles. So therefore I will always have the exact same otherObject, that might be important to you right now. It might be important to you to keep the same object.

[00:06:11]
So that's the the usecase for a ref is to keep track of the exact same thing that is triple equals to each other, right? So if I asked later is otherObject === otherRef.current, right, cuz this is inside of an effect which is gonna happen later, this is still true, right?

[00:06:38]
Now, if you're looking at, say, like when the heck would I ever do that, the answer is probably not very frequently. You don't usually need the triple equals same object. But if you have some sort of animation frame that you're keeping track of or something like that where that the particular object that you're referring to has to be the same one, this is what refs are for.

[00:06:59]
Very niche use case. Okay, that's abstract enough. Does anyone have any questions about refs? It is pretty cool that we can do 3D stuff this easily in the browser these days, all right? This is not that much code to get a little scene going
>> Why do we use ref and passing functions or some data and not props?

[00:07:32]
>> Why do we use refs? So okay, this actually leads me into my next point which is this little thing that I talk about here, memo, okay? So what memo will guarantee you if I do wrap this in memo which, again, you notice this is coming from React.

[00:07:53]
If I provide this exact same props to this component, it won't rerender. Why is this a big deal? This is a really big deal because I have this three.js application. So if it rerenders, I destroy the scene and rerender it. That's bad, right, I wanna keep my scene up there.

[00:08:12]
One, it's expensive to rere, and two, it's janky if I rerender it. So by using memo up here, I can guarantee that as long as the props being passed into the useRef, memo component don't change, it doesn't rerender. So you do this for one of two reasons. One, performance, right?

[00:08:32]
Sometimes you have components that are very expensive to rerender. For example, a three.js scene is very expensive to rerender, right? So using memo, Guarantees that. Now, if you're just doing it with normal React, there's a decent chance that it won't rerender anyway, but you can't guarantee it. The other reason is you have something that would be wrong or bad to rerender, which is typically not the case.

[00:09:02]
Trying to think of an example of that, maybe you have some API request that's timely. Either you have a nonce or something like that and you don't want to rerequest it or something like that. In which case, guaranteeing that it won't rerender it also becomes important. So to answer, going back to that person's question of why is it important to use something like memo or a a ref?

[00:09:27]
If I'm passing an object into a component that has memo, and it's important to me that it doesn't rerender, it's important that it's the same object, right? Because if it's the same object, same shaped object that looks exactly the same but it's not triple equals to each to itself, right?

[00:09:46]
It's gonna cause it to rerender it and we're gonna see which is bad. We'll talk about that in a second cs I'm gonna talk about callback and useMemo and things like that, but that's the idea here. Now, someone's out there thinking like, this is a good idea, I'm gonna wrap everything in memo.

[00:10:06]
Don't do that. That is not what I'm telling you to do. Because memo, now you introduce a new problem of why isn't this rerendering? It's React, you expect everything to rerender when you give it new state and new props. And generally React is very good at rerendering. Do not do performance optimizations until you have a performance problem, okay?

[00:10:27]
Just please do not wrap everything in memo. If you take one thing away from intermediate React, it probably should just be that, right? Use it only when you need it, which is rarely. If you're rendering three.js, yes, rapid memo, if you're not doing anything like that, please don't.

[00:10:44]
Have a problem before you solve a problem, please. Okay, Questions about memo? We'll talk about memo again here in just a second, but any questions about refs?
>> So does it mean that ref helps in memorizing and props don't?
>> Props give you no help in memorizing anything.

[00:11:14]
So if you're using a memo, sorry, if you're using memo to function here. And you're passing objects into that function. You have to use a ref or a useMemo, or a useCallback. I'll talk about those momentarily, so.
>> I do see refs on form inputs often.
>> Yeah, you can use refs to, it's just referring to any DOM node, right?

[00:11:41]
Like I'm reusing a ref to refer to this div right here. Generally you don't need to do it with forms cuz forms, you have events. Events, you can use things like formData and event.target or event.current target. You don't necessarily need to refer to, you don't need a ref to refer to those DOM elements.

[00:11:59]
It's possible when suggested, but I think using events is the cleaner way of doing it. We talk about that in complete intro.

Learn Straight from the Experts Who Shape the Modern Web

  • In-depth Courses
  • Industry Leading Experts
  • Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now