Utilizing the useRef Hook in React
by Jackattack
The useRef hook is a helpful tool that can be used for implementing imperative programming techniques in React, such as accessing and manipulating DOM elements or utilizing third party JavaScript libraries such as JQuery to do so. It returns a mutable object that exists throughout the entire lifecycle of a component.
In this post, I’ll demonstrate common use cases and essential characteristics of refs in a small app I built called weather-logger and techniques that I’ve found helpful. With Weather-Logger, users can input location for which they want to see the current weather. On user submission, an array of location is sent to an express server where we fetch current weather data for each location from https://openweathermap.org/.
To use the useRef hook, the first thing we’ll want to do is ensure that we’re importing it from react. Below, I’m using object de-structuring to extract the particular hooks from react I wish to utilize.
Now we want to initialize a ref variable with the useRef hook in a React component. Ref objects hold a value called current with an initialized value of whatever is passed into the useRef function.
In the image above, let’s ignore the useState calls for now, and draw our focus to the header variable. We now have a ref stored in our variable called header. Let’s console.log header to see what’s inside of it currently.
Right now our header ref is an object with a current property that equals undefined because we have yet to give it a value. If we had passed a value into our useRef function, the current property would be equal to that value. I find refs particularly helpful with DOM manipulation, which requires setting a ref equal to a particular Node/element we are rendering. One way to do so is as such:
In the example above, we use the ref prop on a JSX element, to set its ref property equal to the ref we initialized in the component. Now if we console.log(header), its current property will be the actual element itself which contains all of the DOM properties to which we now have access.
If we were to console.log(header.current), we’d see the actual node displayed in the browser console.
One thing I tend to use the useRef hook for is focusing input elements on component mounting when I want a form to render onto the screen. In the below example, we’ll look into how to useRef to focus an input on componentDidMount with hooks in a component called FormField.
On line 5, we initialize a ref and store it in a variable called form. In our useEffect on line 10, we invoke the focus property within our form ref’s current property on the mounting of our component (indicated by the empty bracket passed as the second argument of the useEffect hook), and finally on line 37, we set the input’s value to our initialized ref thereby giving us access to all the properties intrinsic to input elements as we would find it in the DOM, the focus property being one of them!
As we can see in the gif above, when the app renders on the screen, there is an initial input box that is mounted and is focused, and on click of the plus button next to the form, a new form is rendered and that form’s input is focused upon its mounting!!
The next DOM manipulation use case is certainly helpful and it also reveals some essential traits of refs in general. In the next example, we’re going to create a button that automatically scrolls to a particular component on click.
In our return statement, we have a button on line 33 called that sets our footerDisplay’s state to true on click, and if we navigate to line 44, we see that if footerDisplay is true, we render a component called Footer.
Our Footer component, which admittedly, doesn’t do much of anything besides renders a box with the title of the app, and its located at the bottom of our screen.
Having said that, on the mounting of our FooterComponent, we are using a ref to invoke the scrollIntoView function that immediately scrolls to wherever the location of the Footer component is.
More importantly though, you may notice from the gif that on click of Go to footer a second time that the button no longer scrolls into view. This is because a refs value, though mutable, lasts as long as the component’s lifecycle and since scrollIntoView is only called on mounting of our component, it’ll only work on mounting.
The useRef hook is a very helpful tool that allows us to store, create, access, and manipulate values in our React components in different ways than we could with state for instance. Another area where I’ve found refs particularly helpful is with creating Animations with React Native! I highly recommend you check out use cases for using useRef with the Animated API if you are a React Native practitioner like myself!