Lesson 36 +10 XP

useRef for DOM & Mutable References

useRef for DOM & Mutable References

The useRef hook provides a way to persist mutable values across component re-renders without triggering a re-render when the value changes. It also serves as the primary way to access underlying real DOM nodes in React.

What is a Ref?

Calling useRef(initialValue) returns a plain JavaScript object with a single mutable property: .current.

import { useRef } from 'react';

const myRef = useRef(0);
// Returns object: { current: 0 }

Key Difference: useState vs useRef

FeatureuseStateuseRef
Re-render on change?✅ Yes, updates trigger component re-render❌ No, updating .current does NOT trigger re-render
Access methodState getter variable + setter functionRead & write directly to ref.current
Primary Use CasesRender-affecting data (text, toggles, counters)DOM element manipulation, timer IDs, previous state

Use Case 1: Accessing DOM Elements directly

Pass a ref object to a JSX element's ref attribute. React sets ref.current to the corresponding real DOM node once the component mounts.

import { useRef } from 'react';

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

  const handleFocus = () => {
    // Focus real HTML <input> DOM element directly!
    inputRef.current.focus();
    inputRef.current.style.border = "2px solid blue";
  };

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

Use Case 2: Storing Mutable Variables (e.g. Timer IDs)

function Stopwatch() {
  const [seconds, setSeconds] = useState(0);
  const timerRef = useRef(null); // Holds interval ID across renders

  const startTimer = () => {
    if (timerRef.current !== null) return;
    timerRef.current = setInterval(() => {
      setSeconds(prev => prev + 1);
    }, 1000);
  };

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

  return (
    <div>
      <h3>Time: {seconds}s</h3>
      <button onClick={startTimer}>Start</button>
      <button onClick={stopTimer}>Stop</button>
    </div>
  );
}

Summary & TL;DR

  • useRef(initialValue) returns a { current: value } reference object.
  • Changing ref.current does NOT trigger component re-renders.
  • Use ref attributes to access real DOM nodes for focusing, text selection, or media playback.