Introduction
In this post, we'll look at the useRef()
hook that provides a way to directly access a DOM node. We'll also look at scenarios where we can use the value of the reference returned by the Ref hook that is persisted between component re-renderings.
Prerequisites
- An understanding of the useState() and useEffect() Hook
useRef() Hook
useRef
Hook provides a way to directly access a DOM node within a functional component. In order to use the Ref Hook to access the DOM node, use the following steps
- First, you need to import
useRef
Hook from the react package
import { useRef } from "react"
-
useRef(initialValue)
returns a reference which is a mutable ref object. This returned object will persist for the entire lifetime of the component.
const refObject = useRef(initialValue)
refObject has a current
property that is initialized with the argument passed to useRef
- Now, in order to access the required DOM element, pass a
ref
attribute to that element and assignrefObject
to it.
<input ref={refObject} type="text" />
- Now, you can access the DOM node using
refObject.current
Directly accessing a DOM node should only be done in certain scenarios such as managing focus, text selection and triggering imperative animations.
Now, take a look at the following functional component using the useRef
Hook
import React, { useEffect, useRef } from "react";
export default function App() {
const inputRef = useRef(null);
useEffect(() => {
inputRef.current.focus()
},[])
return (
<div>
<p>Enter email:</p>
<input ref={inputRef} type="text" />
</div>
);
}
Here, the Ref Hook is used to add focus to the input textbox. After the component is rendered to the screen, the useEffect runs and since the inputRef.current
holds the DOM element, inputRef.current.focus()
puts the cursor on the input textbox.
Accessing a DOM node using the ref
attribute is not the only use that useRef
offers. Since, the Ref Hook returns a mutable ref object whose .current
property can hold a value till the entire lifetime of the component, you can use this to keep any mutable value around which can be used later.
useRef()
creates a plain JavaScript object but the difference between useRef()
and creating an object with current property {current: ...}
yourself is that the Ref Hook will give you the same ref object on every render. Additionally, mutating the .current
property does not cause a re-render and therefore useRef
will not notify you when its content changes.
Let's take a look at the following functional component where the Ref Hook is used to keep track of the previous state
import React, { useState, useEffect, useRef } from "react";
export default function App() {
const [version, setVersion] = useState(1)
const prevVersionRef = useRef(0)
useEffect(() => {
prevVersionRef.current = version
})
return (
<div>
<p>Latest Version: {version} Previous Version: {prevVersionRef.current}</p>
<button onClick={() => setVersion(1 + version)}>New Version</button>
</div>
);
}
-
After the App component gets rendered to the screen with a paragraph
Latest Version: 1 Previous Version: 0
and a button, the side effect runs which mutates the.current
property of theprevVersionRef
object to1
. -
As mutating the
.current
property does not cause a re-render and it can hold that value between re-renders; when you click the button to update the version, the component re-renders. -
This causes the
version
to update to2
andprevVersionRef.current
keeps the value1
intact. After the component is re-rendered, the text on the screen updates toLatest Version: 2 Previous Version: 1
. The effect runs again mutating the.current
property to2
.
This is how previous state value can be stored using the Ref Hook.
Now, let's take a look at another example
import React, { useState, useEffect, useRef } from "react";
export default function App() {
const [timer, setTimer] = useState(0)
const timerRef = useRef()
useEffect(() => {
const timerId = setInterval(() => {
setTimer(prevTimerValue => prevTimerValue + 1)
}, 1000)
timerRef.current = timerId
},[])
return (
<div>
<p>Timer: {timer}</p>
<button onClick={() => clearInterval(timerRef.current)}>Clear Timer</button>
</div>
);
}
-
After the App component gets rendered to the screen, React moves to the side effect and sets up a timer using
setInterval
. -
Suppose, you want to clear that timer on click of a button and since the
timerId
variable can only be used inside the Effect Hook, you cannot clear the timer by using that variable in an event handler. -
Therefore, in order to clear the timer from an event handler, you can store the
timerId
to the.current
property of thetimerRef
object and use it inside the event handler to clear the timer on clicking the button.
Conclusion
In this post, you got an understanding on how to use the useRef
hook. We were able to access a DOM element and provide focus to it using the Ref hook. We also looked at scenarios where we used the value stored in .current
property of the mutable ref object.
Thanks for taking the time to read this post. I hope this post helped you!!😊😃 If you liked it, please share.
It would be great to connect with you on Twitter. Please do share your valuable feedback and suggestions👋
Comments (0)