Use the React useRef Hook to Reference a DOM Element or Simulate an Instance Variable

Share this video with your friends

Send Tweet

Refs have been a handy way to reference DOM elements in Class Components, but did you know you can use refs for other things as well? In this lesson, we’ll examine how to leverage the useRef hook inside a Function Component. We’ll first use this ref to attach to a React element, which you may already be familiar with, but then we’ll examine how to use a ref to simulate a Class instance variable.

Alex Ung
Alex Ung
~ 6 years ago

Thanks for the videos. If the todoId can be kept track of using either useState or useRef, what are the pros and cons to each approach?

Elijah Manor
Elijah Manor(instructor)
~ 6 years ago

Alex, good question about where to keep todoId. You could technically do either as you mentioned, but I lean toward keeping data that is needed for the render inside of useState. In this case the todoId isn't needed for the render, but is intended to keep track of the last ID so it can be incremented when a new item is added. Technically that variable could be stored anywhere (even global, but I prefer to limit global variables).

Tony Catalfo
Tony Catalfo
~ 6 years ago

This course is wonderful! Putting everything on codesandbox helps tremendously. I was wondering what the reason was to have this line of code inputRef.current.focus(); line 30 of the focus example. Don't we get the same result if we just use line 31? inputRef.current.select();

Thanks Anthony

Tony Catalfo
Tony Catalfo
~ 6 years ago

What is the advantage of useRef over something like this: let count = Number(window.localStorage.getItem('count') || 0) let incCount =()=>{ window.localStorage.setItem('count', count + 1) return count+1 }
.... // todoId.current id: incCount() , text: newTodo, completed: false

Tony Catalfo
Tony Catalfo
~ 6 years ago

id: incCount() , text: newTodo, completed: false

Elijah Manor
Elijah Manor(instructor)
~ 6 years ago

Tony, good question. MDN notes that...

Calling element.select() will not necessarily focus the input, so it is often used with HTMLElement.focus().

https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/select

Elijah Manor
Elijah Manor(instructor)
~ 6 years ago

Tony, another good question. It'd be better if the UI didn't figure out the IDs in the first place, but since there is no server counterpart the UI is doing the logic. You could introduce another localStorage item that you always keep up to date with the largest ID known, however, if that number was based on count it could lead to bugs. Imagine you had 10 items and deleted 5 of them. If it was based on count, then the next item you create could reuse an existing ID (depending on what you deleted). So, that is why when the app loads I iterate through the todos and look for the Max ID and set that to the ref. You could also store that to localStorage, but you'd need to keep it up-to-date and make sure it kept track of the largest ID that exists. If you had TONS of data in localStorage then my solution may be slower on startup since I do a loop, but browsers are pretty fast so I don't think that's a worry.

Kostiantyn Hryshyn
Kostiantyn Hryshyn
~ 5 years ago

why not just write let todoId = 0; and then just change todoId++ value? =)

Jaime Vega
Jaime Vega
~ 5 years ago

why not just write let todoId = 0; and then just change todoId++ value? =)

Because the values of local variables inside the function are gone after each render. So according to your suggestion, todoId will always be zero. When putting the values in state of refs, the values it contains are persisted between renders.

Alexander Myshov
Alexander Myshov
~ 5 years ago

why not just write let todoId = 0; and then just change todoId++ value? =)

Creating variable outside of the function can do the trick and retain value between rerenders but there is a small issue. Every instance of component in the application will share the same value.