R

React Handbook

Clean • Professional

React useRef Hook: Access DOM & Store Mutable Values

3 minute

React useRef Hook

The useRef hook is a powerful tool that allows you to access DOM elements directly and store mutable values that persist across renders without causing re-renders.

This makes useRef ideal for tasks like focusing inputs, tracking previous values, storing timers, or managing any mutable variable in functional components.

What is useRef?

The useRef hook returns a mutable ref object with a .current property:

const refContainer = useRef(initialValue);
  • refContainer → an object with a property .current
  • .current → stores the value or reference
  • Updating .current does not trigger a re-render

Importing useRef

import React, { useRef } from "react";

Accessing DOM Elements

One of the most common uses of useRef is to reference a DOM element directly.

Example – Focusing an Input Field:

import React, { useRef } from "react";

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

  const handleFocus = () => {
    inputRef.current.focus(); // Access DOM element
  };

  return (
    <div>
      <input ref={inputRef} type="text" placeholder="Type here..." />
      <button onClick={handleFocus}>Focus Input</button>
    </div>
  );
}

export default FocusInput;
  • ref={inputRef} attaches the ref to the input element.
  • inputRef.current.focus() directly calls the DOM method focus().
  • This avoids using document.querySelector and keeps React in control.

Storing Mutable Values Without Re-rendering

useRef can also store any value that persists across renders:

Example – Tracking Render Count:

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

function RenderCounter() {
  const [count, setCount] = useState(0);
  const renderCount = useRef(0);

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

  return (
    <div>
      <h2>Count: {count}</h2>
      <h3>Render Count: {renderCount.current}</h3>
      <button onClick={() => setCount(count + 1)}>Increment</button>
    </div>
  );
}

export default RenderCounter;
  • renderCount.current stores the number of renders.
  • Updating .current does not trigger component re-render, unlike useState.
  • Perfect for tracking previous values, timers, or any mutable data.

Combining useRef with useEffect – Previous State

You can use useRef to store the previous state of a component:

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

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

  useEffect(() => {
    prevCount.current = count; // Store previous value
  }, [count]);

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

export default PreviousValueExample;

Common useRef Use Cases

  1. Accessing DOM Elements
    • Focusing input fields
    • Measuring dimensions
    • Scrolling to elements
  2. Storing Mutable Values
    • Previous state
    • Timer IDs (setInterval / setTimeout)
    • Flags that don’t require re-render
  3. Integrating with Third-Party Libraries
    • Storing references for chart libraries, maps, or custom plugins

Key Points About useRef

  • .current can store any value (DOM element, number, object, etc.)
  • Updating .current does not trigger re-render
  • Ideal for persistent mutable values
  • Often used with useEffect for side effects or tracking previous state

Example – useRef with Timer

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

function Timer() {
  const [seconds, setSeconds] = useState(0);
  const intervalRef = useRef(null);

  useEffect(() => {
    intervalRef.current = setInterval(() => {
      setSeconds(s => s + 1);
    }, 1000);

    return () => clearInterval(intervalRef.current); // Cleanup on unmount
  }, []);

  return <h2>Seconds: {seconds}</h2>;
}

export default Timer;

 

Article 0 of 0