Introduction
There are times when frequent changes in React components must be tracked without requiring the component to be rerendered. It's also possible that the component needs to be rerendered efficiently. While the useState and useReducer hooks are the React API for managing local state in a React component, they can be called too frequently, causing the component to rerender for each call to the update functions.
This article is a deep dive into how we overcome the issues mentioned above with the help of the useRef hook.
So without further ado, let’s get started!
What is useRef?
A hook is a unique function that allows you to access state and other React features without having to write ES6 class components, which are notoriously difficult to comprehend and use.
The useRef hook is a function that takes at most one argument and returns an object. The returned object has a property called current, whose value is the argument passed to useRef. If invoked without an argument, the returned object’s current property is set to undefined.
Also read, ReactJS
Uses of useRef hook:
The useRef hook is mainly intended to serve two primary purposes:
●To directly access DOM nodes
●To persist a mutable value in successive renders
Let’s see them one by one.
Accessing DOM elements
One of the useful applications of the useRef hook is to access DOM elements. Consider an example where we want to access an input element through the DOM. Instead of using the methods like document.getElementById, document.querySelector we used in vanilla javascript, we can make use of the useRef hook.
There are three simple steps to do the same:
- Create a reference to access the element
- The ref attribute of the element is then assigned to this reference.
- After mounting to the DOM, the current property of the reference points to the DOM element.
Example:
In the below given code snippet, we are creating the element counterEl as a reference. And the ref attribute of the span is then assigned to the counterEl.
const { useState, useRef } = React const Counter = () => { const [count, setCount] = useState(0) const counterEl = useRef(null) // Creating a reference const increment = () => { setCount(count + 1) console.log(counterEl) } return ( <> Count: <span ref={counterEl}>{count}</span> // Assigning the reference <button onClick={increment}>+</button> </> ) } ReactDOM.render(<Counter />, document.getElementById('app')) |
Now, let’s see the second use of the useRef hook.
2. To persist mutable values
Let us consider the reference object we created earlier. Any change that we make to this reference object will persist across all renders of our React component.
At this point, you probably think we could use the useState hook for this, and you would also be correct in most of the cases. But, consider the scenario wherein you want to count and display the number of renders in the UI. If you store this information in the state and update the state on every render, calling setState would cause another render, resulting in an Infinite loop!
In this scenario, we can store the information in a reference that would persist between renders, but its state would not be updated.
Things might have gotten a little confusing but let’s try and understand with the help of the following example.
Since we can persist values with the help of the useRef hook, we can also use it to keep track of the previous state values with the help of two other hooks: useState and useEffect.
import { useState, useEffect, useRef } from "react"; import ReactDOM from "react-dom"; function App() { const [inputValue, setInputValue] = useState(""); const previousInputValue = useRef(""); useEffect(() => { previousInputValue.current = inputValue; }, [inputValue]); return ( <> <input type="text" value={inputValue} onChange={(e) => setInputValue(e.target.value)} /> <h2>Current Value: {inputValue}</h2> <h2>Previous Value: {previousInputValue.current}</h2> </> ); } |
An important thing to note in the above problem is when we save the previous state in useEffect, we do not want the component to rerender. Otherwise, it would go into an infinite loop. Here’s when useRef comes into the picture!
Now, let’s move on to some of the frequently asked questions of this topic.
Also See, Hooks in React JS