Hooks 11 exercises
explainer

Refs in React

Let's look at the refs you can pass to HTML elements.

Most HTML elements will accept a ref, which will be of a shape that we've seen so far with useRef.

In this example, hovering over div will show us that it is JSX.IntrinsicElements.div:


export const nullAsRef = (
<div

Loading explainer

Transcript

0:00 Let's take a minute and talk about refs that you can pass to HTML elements. What you can do here is that a lot of different properties, most HTML elements will accept a ref. This ref is going to be of a shape that we've seen so far with the useRef. Now this ref here, what we can do is this div, it's got IntrinsicElements.div.

0:24 This ref, if we command-click on it, we can see that it's got a LegacyRef or undefined. You can pass several different things into this ref. You can pass an object with current , but you can't pass in, for instance, current like a random string. This has to be or a HTMLDivElement.

0:45 We could potentially do document.createElement div, and that would work, but I just want to show you all the different ways that refs can express themselves. You can pass in a ref as a string. This is like a legacy React API. If we command-click onto here, we can see that it's accepting a LegacyRef.

1:05 This LegacyRef is a string or a ref. Now this ref is a RefCallback or RefObject or . A RefCallback is like a function. It's got a strange bivarianceHack -- Don't ask me about this -- that takes in the thing and then returns void. This looks a little bit like...Where's the CallbackRef? Here it is.

1:31 This ref here, you can see that it's got HTMLDivElement or . I assume this is because this function, when you pass it into this ref slot, whenever it gets updated, it gets updated with that new value. It could be updated with a div element or it could be updated to .

1:50 There is another type here. What's the other type of ref? RefObject which has a current T or here. This is the one that we saw before. This is a RefObject. This one is a string ref or a LegacyRef. This one is a RefCallback. Notice how you can't pass undefined into a ref here. Ref.current can never be undefined.

2:16 This is going to come up a lot later. It's a little bit not very ergonomic, but there's a strong reason for it. The reason is that when this div is unmounted, let's look at this. Why is this HTMLDivElement or instead of HTMLDivElement or undefined?

2:35 When this div gets unmounted, React is going to set this thing inside here. It's going to call this function with an empty value. React has chosen that empty value as , not undefined. That means then that undefined, what they've chosen to do in the types is they've chosen to make undefined not assignable to this current value here.

2:58 Because when you pass a ref to a div like this, React is going to manage that ref for you, and it's going to say, "OK, I'm going to set that ref to when this div gets unmounted." You can pass to a ref, you can pass strings to a ref, you can pass a object, a RefObject, to a ref, but you can't pass undefined as part of that or you can pass a callback that has the value inside it or .

3:31 Undefined is not preferred over . Null is React's button value or rather it's value that it sets it when it's nullish and when it's unmounted. There you go. That's a really nice explanation about how these different values can be passed around as refs in React.