DevAcademy
LearnReactuseRef & Refs
IntermediateReact

useRef & Refs

Learn how to access DOM nodes directly and persist mutable values across renders without triggering re-renders, using useRef.

Reading Time

14 min

Lesson

Lesson 17 of 42

What is a Ref?

A ref is a mutable value that persists across renders, similar to state — but unlike state, changing a ref does not trigger a re-render. useRef(initialValue) returns an object with a single .current property.

A Basic Ref

import { useRef } from "react";

function Example() {
  const renderCount = useRef(0);
  renderCount.current += 1;

  return <p>This component has rendered {renderCount.current} times.</p>;
}

Accessing DOM Elements

The most common use of a ref is to get direct access to a DOM node — for example, to call .focus() on an input, which isn’t something you can do declaratively through props alone.

Focusing an Input on Mount

import { useRef, useEffect } from "react";

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

  useEffect(() => {
    inputRef.current.focus();
  }, []);

  return <input ref={inputRef} placeholder="Search..." />;
}

Refs vs State

State is for values that affect what’s rendered on screen — changing state re-renders the component. Refs are for values you need to keep around between renders, but that shouldn’t trigger a re-render when they change.

State vs Refs

State (useState)Refs (useRef)
Triggers a re-render on changeYesNo
Value persists between rendersYesYes
Typical useData shown in the UIDOM access, timers, values that don’t affect rendering

Storing a Timer ID in a Ref

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

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

  function stop() {
    clearInterval(intervalRef.current);
  }

  return (
    <>
      <p>{seconds}s</p>
      <button onClick={start}>Start</button>
      <button onClick={stop}>Stop</button>
    </>
  );
}

Don’t Read or Write Refs During Rendering

Reading or writing ref.current while a component is rendering makes rendering unpredictable, since refs don’t follow React’s usual re-render rules. Only access refs inside event handlers or effects, not directly in the render body.

Best Practice

Reach for a ref only when you specifically need to escape React’s declarative model — direct DOM access, storing a mutable value like a timer ID, or measuring an element’s size. If a value affects what’s rendered, it belongs in state instead.

Interview Questions

Quick Quiz

1. Does updating a ref’s .current value trigger a re-render?

2. What is the most common use for a ref attached to a JSX element?

3. Where should you read or write a ref’s value?