Refs

⭐ Interview Importance: MEDIUM
⏱️ Revision Time: 2 min

Refs

A Ref (short for Reference) is a special feature in React that allows you to directly access a DOM element or persist a mutable value across renders without causing the component to re-render.

In functional components, you create a ref using the useRef hook.

The Problem Refs Solve

React is fundamentally declarative. You define state, and React figures out how to update the DOM to match that state (UI = f(state)).

However, there are times when you need to step outside of this declarative model and interact with the DOM imperatively.

Common use cases for Refs include:

  1. Managing focus, text selection, or media playback (e.g., calling input.focus() or video.play()).
  2. Measuring the size or position of a DOM node.
  3. Integrating with third-party, non-React DOM libraries (like D3.js, GSAP, or a jQuery plugin).

How to Use a Ref for the DOM

  1. Create a ref using useRef(null).
  2. Pass the ref object as the ref attribute to a JSX element.
  3. Access the DOM node via the ref.current property.
import { useRef } from 'react';

function TextInput() {
  // 1. Create a ref
  const inputRef = useRef(null);

  const focusInput = () => {
    // 3. Access the actual DOM node using .current
    inputRef.current.focus();
  };

  return (
    <div>
      {/* 2. Attach the ref to the element */}
      <input ref={inputRef} type="text" />
      <button onClick={focusInput}>Focus</button>
    </div>
  );
}

The current Property

When you pass a ref object to a React element (<div ref={myRef} />), React will wait until the component has mounted (been added to the DOM), and then it will assign the actual DOM node to the myRef.current property.

When the component unmounts, React will automatically set myRef.current back to null.

Important: Because ref.current is not set until after the initial render, you should not try to access it directly inside the main body of your component. You should only access it inside event handlers or inside useEffect / useLayoutEffect.

function MyComponent() {
  const divRef = useRef(null);

  // ❌ BAD: divRef.current is null during the initial render!
  // console.log(divRef.current.clientWidth); 

  useEffect(() => {
    // ✅ GOOD: Inside useEffect, the component has mounted, so .current exists
    console.log(divRef.current.clientWidth);
  }, []);

  return <div ref={divRef}>Hello</div>;
}

Interview Questions

Q: When should you explicitly avoid using refs?
A: You should never use a ref as a substitute for State. If you find yourself reading a ref’s value to decide what to render on the screen, or trying to display a ref’s value inside JSX, you are doing it wrong—that data belongs in useState.