How to Use useRef in React Functional Components

Recently, while working on a React project for a client in New York, I needed a way to access a DOM element directly without triggering a re-render. That’s when I turned to the useRef hook.

If you’ve ever used document.getElementById() in vanilla JavaScript, useRef gives you that same power, but in the React way. It’s simple, efficient, and helps keep your component performance smooth.

In this tutorial, I’ll show you how I use useRef in React functional components. We’ll look at two practical methods, one for accessing DOM elements and another for storing mutable values that persist across renders.

What is useRef in React?

The useRef hook is a part of React’s built-in Hooks API. It lets you create a reference to a value or DOM element that persists between renders, without causing the component to re-render when it changes.

Think of it as a “box” that holds a value. You can read or update what’s inside that box anytime, and React won’t re-render your component.

Here’s the basic syntax:

import React, { useRef } from 'react';

function MyComponent() {
  const myRef = useRef(initialValue);
  // myRef.current holds the value
}

Method 1 – Use useRef to Access a DOM Element

One of the most common ways I use useRef is to directly manipulate or focus an input element, something you can’t easily do with state alone.

Let’s say you have a form where users enter their ZIP code, and you want to automatically focus the input field when the page loads.

Here’s how I do it:

Example: Focusing an Input Field Using useRef

import React, { useRef, useEffect } from 'react';

function ZipCodeForm() {
  const inputRef = useRef(null);

  useEffect(() => {
    // Automatically focus the input when the component mounts
    inputRef.current.focus();
  }, []);

  const handleSubmit = (e) => {
    e.preventDefault();
    alert(`ZIP Code entered: ${inputRef.current.value}`);
  };

  return (
    <form onSubmit={handleSubmit} style={{ textAlign: 'center', marginTop: '50px' }}>
      <label htmlFor="zipcode">Enter Your ZIP Code: </label>
      <input
        id="zipcode"
        type="text"
        ref={inputRef}
        placeholder="e.g., 10001"
        style={{ padding: '8px', marginRight: '10px' }}
      />
      <button type="submit">Submit</button>
    </form>
  );
}

export default ZipCodeForm;

I executed the above example code and added the screenshot below.

useRef in React Functional Components

How it works:

  • I first created a reference using useRef(null).
  • Then, in the useEffect hook, I called inputRef.current.focus() to automatically focus the input field when the component mounts.
  • Since useRef doesn’t trigger re-renders, this approach is fast and efficient.

This is perfect for login forms, search boxes, or any place where you want to improve user experience.

Method 2 – Use useRef to Store Mutable Values

Another powerful use case for useRef is to store values that persist between renders, without causing re-renders.

For example, I once built a small timer app where I needed to store the setInterval ID. Using state for that would cause unnecessary re-renders, so I used useRef instead.

Example: Stopwatch Using useRef

import React, { useState, useRef } from 'react';

function Stopwatch() {
  const [time, setTime] = useState(0);
  const timerRef = useRef(null);

  const startTimer = () => {
    if (timerRef.current !== null) return; // Prevent multiple intervals
    timerRef.current = setInterval(() => {
      setTime((prevTime) => prevTime + 1);
    }, 1000);
  };

  const stopTimer = () => {
    clearInterval(timerRef.current);
    timerRef.current = null;
  };

  const resetTimer = () => {
    stopTimer();
    setTime(0);
  };

  return (
    <div style={{ textAlign: 'center', marginTop: '50px' }}>
      <h2>Stopwatch</h2>
      <h3>{time} seconds</h3>
      <div>
        <button onClick={startTimer}>Start</button>
        <button onClick={stopTimer}>Stop</button>
        <button onClick={resetTimer}>Reset</button>
      </div>
    </div>
  );
}

export default Stopwatch;

I executed the above example code and added the screenshot below.

Use useRef in React Functional Components

What’s happening here:

  • I used timerRef to store the interval ID.
  • Because useRef persists across renders, the interval keeps running even when React re-renders the component.
  • When I stop or reset the timer, I can easily clear the interval using clearInterval(timerRef.current).

This method is great for timers, animations, or tracking previous values without re-rendering your component.

Method 3 – Use useRef to Track Previous Values

Sometimes, you might want to compare the previous value of a prop or state variable with its current value. I often use this when debugging or optimizing performance.

Here’s how I do it:

Example: Tracking Previous State with useRef

import React, { useState, useEffect, useRef } from 'react';

function PreviousValueExample() {
  const [count, setCount] = useState(0);
  const prevCountRef = useRef();

  useEffect(() => {
    prevCountRef.current = count;
  }, [count]);

  const prevCount = prevCountRef.current;

  return (
    <div style={{ textAlign: 'center', marginTop: '50px' }}>
      <h2>Count: {count}</h2>
      <h3>Previous Count: {prevCount}</h3>
      <button onClick={() => setCount(count + 1)}>Increase</button>
    </div>
  );
}

export default PreviousValueExample;

I executed the above example code and added the screenshot below.

useRef Functional Components in React

How it works:

  • I created a prevCountRef using useRef().
  • Inside useEffect, I updated it after each render.
  • This gives me access to the previous value of count without triggering a re-render.

This trick is super handy when you need to compare state changes, for example, tracking user actions or detecting changes in form inputs.

Common Mistakes When Using useRef

Here are a few things I’ve learned from experience:

  1. Don’t expect re-renders when updating ref.current.
    Changing a ref’s value won’t cause the component to re-render; that’s by design.
  2. Always initialize your ref properly.
    If you plan to attach it to a DOM element, start with useRef(null).
  3. Avoid overusing refs.
    If you can manage something with state, use state. Refs are best for DOM access or storing mutable values.

When Should You Use useRef?

Here’s a quick summary of when I use useRef in real-world React apps:

Use CaseDescription
Access DOM elementsFocus input fields, scroll to elements, play/pause videos
Store mutable valuesTrack timers, intervals, or previous values
Avoid re-rendersKeep data between renders without triggering updates

When I first started using React Hooks, I underestimated how powerful useRef could be. But over the years, it’s become one of my favorite tools for managing DOM interactions and keeping components lightweight.

Whether you’re building a data entry form for a U.S. business dashboard or a simple stopwatch app, mastering useRef will make your React code cleaner and more efficient.

You may read:

Leave a Comment

51 Python Programs

51 PYTHON PROGRAMS PDF FREE

Download a FREE PDF (112 Pages) Containing 51 Useful Python Programs.

pyython developer roadmap

Aspiring to be a Python developer?

Download a FREE PDF on how to become a Python developer.

Let’s be friends

Be the first to know about sales and special discounts.