How to Use useRef in React: DOM Manipulation & More

In React, the useRef hook is useful for interacting with the DOM and maintaining values across renders without causing re-renders.

In this post, you’ll learn everything about useRef, including how it works, its use cases, and best practices with examples.

Let’s jump right into it!🚀

What is useRef in React?

useRef is a React Hook that returns a mutable reference object.

This reference persists across renders but does not trigger a re-render when updated. To put it simply, when a component’s state changes, React updates the UI by re-rendering the component. But useRef stores values without triggering this update.

You can think of useRef as a sticky note on your desk. You can update what’s written on it, but it doesn’t affect the layout of your desk. Similarly, useRef stores a value without causing your component to refresh.

Why use useRef in React?

The useRef hook is useful for:

  • Accessing and modifying DOM elements directly.
  • Storing values between renders without causing re-renders.
  • Tracking previous values in a component.

Basic Syntax of useRef

Before using useRef, you need to import it from React:

import { useRef } from "react";

Syntax:

const myRef = useRef(initialValue);

Here,

  • useRef(initialValue): Returns an object { current: initialValue }
  • The reference persists across renders but does not cause re-renders when updated.
  • You can update the value using myRef.current.

For example:

import { useRef } from "react";

function Example() {
  const countRef = useRef(0); // Creates a ref with initial value 0

  const handleClick = () => {
    countRef.current += 1; // Updates ref value (no re-render)
    console.log("Current count:", countRef.current);
  };

  return (
    <div>
      <button onClick={handleClick}>Increment</button>
    </div>
  );
}

Here,

  • countRef is a mutable reference storing a value.
  • Clicking the button updates countRef.current, but the UI does not re-render.
  • The new value is logged in the console.

Use Case of useRef in React

Use Case 1: Accessing DOM Elements

If you need to access a DOM element directly without using document.querySelector, you can use the useRef hook.

Example: Setting focus on an input field

import { useRef } from "react";

function FocusInput() {
  const inputRef = useRef(null); // Create Ref

  const handleClick = () => {
    inputRef.current.focus();  // This will focus on the input field
  };

  return (
    <div>
      <input ref={inputRef} type="text" placeholder="Enter text" />
      <button onClick={handleClick}>Focus Input</button>
    </div>
  );
}

export default FocusInput;

In this example,

  • useRef(null) creates a reference to store the input element.
  • ref={inputRef} connects the reference to the input field.
  • inputRef.current.focus() sets focus on the input field when the button is clicked.

Use Case 2: Store Value Without Re-render

If you need to store a value without re-rendering a component, you can use the useRef hook.

Example: Tracking the re-render count

import { useState, useRef, useEffect } from "react";

function RenderCounter() {
  const [count, setCount] = useState(0);
  const renderCount = useRef(0); // Mutable Value (This will not re-render)

  useEffect(() => {
    renderCount.current += 1; // Increment render count
  });

  return (
    <div>
      <p>Count: {count}</p>
      <p>Component Re-rendered: {renderCount.current} times</p>
      <button onClick={() => setCount(count + 1)}>Increment</button>
    </div>
  );
}

export default RenderCounter;

In this example,

  • renderCount persists across renders without causing extra re-renders.
  • Using useState instead of useRef here would cause an unnecessary re-render each time renderCount is updated.

Use Case 3: Track the previous value

You can use the useRef hook to store the previous value of a state.

Example:

import { useState, useEffect, useRef } from "react";

function PreviousValueTracker() {
  const [count, setCount] = useState(0);
  const prevCountRef = useRef(); // This will store previous value

  useEffect(() => {
    prevCountRef.current = count;  // Update Previous Value
  }, [count]);

  return (
    <div>
      <p>Current Count: {count}</p>
      <p>Previous Count: {prevCountRef.current}</p>
      <button onClick={() => setCount(count + 1)}>Increment</button>
    </div>
  );
}

export default PreviousValueTracker;

Here,

  • prevCountRef stores the previous value of count.
  • useEffect updates prevCountRef.current whenever count changes.

useRef vs useState: When to use?

FeatureuseRefuseState
Value PersistenceYes, persists across rendersYes, persists across renders
Re-render TriggerNo re-render on updateTriggers re-render
Use CaseDOM access, previous valuesUI updates, state management
Initial Value{ current: initialValue }Any data type supported
  • If you need to update the UI, use the useState hook.
  • If you need to store a value without triggering a re-render, use the useRef hook.

Best Practices & Common Mistakes of useRef

Mistake: Using useRef for UI updates

const countRef = useRef(0);

const increment = () => {
  countRef.current += 1;
  console.log(countRef.current); // This will update the value, but not the UI
};

Best Practice: For UI updates, use the useState hook.

Mistake: Using useRef for executing side effects

function App() {
  const ref = useRef(0);

  if (ref.current === 0) {
    console.log("Component mounted!"); // This will execute multiple times
  }

  ref.current++;
}

Here, useRef values persist between renders, but component re-renders don’t reset their value. So the condition (if (ref.current === 0)) will always be true on re-render, causing repeated execution.

Best Practice: Use the useEffect hook for side effects.

Example:

useEffect(() => {
  console.log("Component mounted!");
}, []);

Why You Need useRef?

  • Efficiently access DOM elements.
  • Store values across renders without unnecessary re-renders.
  • Track previous state values.

Learn about useReducer hook in React!


That’s all for today!

If you’re new to web development, check out Learnify — my curated platform with beginner-friendly tutorials to help you learn web development step-by-step with examples and simple explanations.

If you enjoy my work and want to support what I do buy me a coffee!

Every small gesture keeps me going! 💛

Follow me on X (Twitter) to get daily web development tips & insights.


Enjoyed reading? You may also find these articles helpful.

14 Essential React Concepts Every Developer Must Know

Top 10 React Component Libraries You Should Know

Leave a Comment