In React, Hooks are special functions that allow developers to use state and other features of React without the need for class components. Among these hooks, the useRef Hook stands out as a valuable tool for managing values and accessing Document Object Model (DOM) elements.

The useRef Hook is a powerful tool that offers immense flexibility and capabilities, but developers often misunderstand and misuse it.

In this article, we will delve into the depths of the useRef Hook, demystifying its purpose, functionality, and best practices. By the end of this guide, you will understand what the Hook is all about and gain valuable insights into how to harness its full potential effectively.

What Is the useRef Hook?

The useRef Hook serves two main purposes: storing mutable values that do not cause a re-render when updated and storing references to DOM elements. Let’s explore how it works in more detail.

When a component renders in React, its state and other variables are typically reset. However, there are cases where you need to retain certain values even when the component re-renders. This is where the useRef Hook comes into play. It allows you to create a reference to a value that will persist between renders, ensuring that the value remains intact even if other parts of the component change.

Additionally, the useRef Hook is instrumental in working with DOM elements. In React, accessing and modifying DOM elements directly can be challenging, especially without the useRef Hook. With useRef, you can obtain a reference to a specific DOM element and perform operations on it. This eliminates the need for external libraries or convoluted workarounds.

Implementing useRef in React

To start using the useRef Hook in your React project, import it from the React package:

import { useRef } from 'react';

Once imported, you can declare a ref variable within your functional component using the useRef Hook:

const myRef = useRef();

Now, you have a ref object, myRef, that you can use to store and access values. To use the myRef variable with any element, assign it to the ref prop of the element.

<div ref={myRef}>This is an example element</div>

In the above example, you assign the div element a ref prop. This allows you to reference and access the element using the myRef variable elsewhere in the component.

To access the value stored in the reference created, you can use the .current property of the myRef object.

const myRefValue = myRef.current;
console.log(myRefValue); // <div>This is a sample div</div>

DOM Manipulation With the useRef Hook

Manipulating the DOM is a common task in web development because it allows you to dynamically change and update the content, structure, and appearance of a web page.

In traditional JavaScript development, accessing and manipulating DOM elements required using methods like getElementById, querySelector, or getElementsByClassName to select specific elements from the document. Once selected, you can update content, modify styles, or attach event listeners.

// HTML
<div>
  <input type="text" id="myInput" />
  <button id="focusButton">Focus Input</button>
</div>
// JavaScript
<script>
      const inputRef = document.getElementById('myInput');
      const focusButton = document.getElementById('focusButton');
      const handleFocus = function() {
        inputRef.focus();
      };
      focusButton.addEventListener('click', handleFocus);
</script>

However, when working with DOM elements in a React component, the process is not the same due to the component’s virtual DOM and the need to manage updates efficiently. Developers often resorted to various approaches, such as using refs or external libraries like jQuery, to access and manipulate DOM elements.

With the introduction of the useRef Hook in React, the process of working with DOM elements within components has become significantly streamlined. The useRef Hook provides a straightforward way to create a reference to a DOM element, making it easily accessible and manipulable within the component’s context.

import { useRef } from 'react';

const FocusComponent = () => {
  const inputRef = useRef(null);

  const handleFocus = () => {
    // accessing the input element
    let inputElement = inputRef.current;

   // modify the DOM element
   inputElement.focus();
  };
 
 return (
    <div>
      <input type="text" ref={inputRef} />
      <button onClick={handleFocus}>Focus Input</button>
    </div>
  );
}

In this example, the useRef Hook is used to create a reference inputRef that points to the input element. When the “Focus Input” button is clicked, the handleFocus function utilizes inputRef.current.focus() to set the focus on the input element directly. This demonstrates how the useRef Hook simplifies the process of working with DOM elements in React.

Another example is you want to manipulate a div by changing its background when a button is clicked:

import { useRef } from 'react';

const ExampleComponent = () => {
  const divRef = useRef();

  const handleClick = () => {
    divRef.current.style.backgroundColor = 'red';
  };

  return (
    <div>
      <div ref={divRef}>This is a sample div</div>
      <button onClick={handleClick}>Change Color</button>
    </div>
  );
}

In this example, you create a reference with the useRef Hook called divRef. You assign this reference to the ref prop of the div element.

When the “Change Color” button is clicked, the handleClick function is invoked. In the function, you can access the div element with divRef.current. In this case, you modify the background color of the div element by updating its style.backgroundColor property to ‘red’.

divRef.current.style.backgroundColor = 'red';

Preserving Values Across Re-renders

Preserving values across re-renders is a powerful use case of the useRef Hook. It is particularly useful when you have values that need to persist throughout the component’s lifecycle without triggering a re-render.

To better understand this concept, let’s compare the useRef Hook with the useState Hook using real examples:

Example with useState Hook:

import { useState } from 'react';

function CounterComponent() {
  const [count, setCount] = useState(0);

  const increment = () => {
    setCount(count + 1);
  };

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={increment}>Increment</button>
    </div>
  );
}

In this example, you use the useState Hook to manage the count state variable. Whenever the increment function is called, the count state is updated using setCount. This triggers a re-render of the component, reflecting the updated count value.

Page re-renders with the useState Hook

Example with useRef Hook:

import React, { useRef } from 'react';

function CounterComponent() {
  const countRef = useRef(0);

  const increment = () => {
    countRef.current = countRef.current + 1;
    console.log('Count:', countRef.current);
  };

  return (
    <div>
      <p>Count: {countRef.current}</p>
      <button onClick={increment}>Increment</button>
    </div>
  );
}

In this example, you use the useRef Hook to create a countRef variable, initialized with an initial value of 0. Whenever the increment function is called, you directly update the countRef.current value without triggering a re-render. The updated value is logged to the console.

Page does not re-renders with the useRef Hook

By using the useRef Hook, the component doesn’t re-render when the countRef.current value changes. This can be advantageous in scenarios where you have values that need to be modified but don’t affect the rendering process.

Note that when using the useRef Hook in this manner, changes to the ref value won’t automatically trigger re-renders. If you need to reflect the updated value in the UI, you can either manually handle the update or combine the useRef Hook with other hooks or state variables to achieve the desired behavior.

Summary

In this article, you explored the useRef Hook in React, understanding its purpose, implementation, and practical applications. You learned how to use useRef for accessing and modifying DOM elements and preserving values.

A best practice for using the useRef Hook is to avoid overusing it. Use it when you specifically need to access and manipulate DOM elements or preserve values across re-renders.

The useRef Hook can also be used for various practical scenarios like animations and transitions, caching values or intermediate results, and lots more which makes your React application stand out.

Build your next React application and deploy it for free to Kinsta’s Application hosting so you can access it live and share it with the world!

Now it’s your turn. What is your thought on the useRef Hook? Please feel free to share it with us in the comments section below.