useRef hook in React

Pratyksh
Last Updated: May 13, 2022

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.

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.getElementByIddocument.querySelector we used in vanilla javascript, we can make use of the useRef hook. 

 

There are three simple steps to do the same:

 

  1. Create a reference to access the element
  2. The ref attribute of the element is then assigned to this reference.
  3. 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.

Frequently Asked Questions

  1. What is a ref?
    Answer: Refs provide a way to access DOM nodes or React elements, and they can be created using the useRef hook and the createRef hook.

 

2. What are the differences between useRef and useState hooks?
Answer: One similarity between the useRef and useState hooks is that they both persist a value across rerenders of a component.
The value tracked by useState triggers a rerender, whereas the value tracked by useRef does not trigger a rerender.
 

3. What is the difference between useRef and createRef?
Answer: As the name clearly suggests, createRef creates a new ref object every time it runs, whereas useRef only creates a ref object when it is first rendered. This, in turn,  implies that createRef does not persist existing values between renders.

4. When should you not use useRef?
Answer: The idea of useRef might be tempting to some developers, but the default approach should be to use React’s states and props which would make the codebase easy to maintain.

Key Takeaways

The useRef hook is a great tool to directly manipulate the DOM and persist data between renders without causing a rerender. The latter is handy when combined with other hooks like useEffect and useState.

So this was all about the useRef hook in react. If you want to learn advanced front end web development, Coding Ninjas has one of the best courses available, which you can find here.
 

Thank you for reading!

Was this article helpful ?
0 upvotes

Comments

No comments yet

Be the first to share what you think