Accessing the DOM: The `useRef` Hook

Gain a direct line to the DOM and manage persistent values without triggering re-renders.

Lesson ProgressStep 1 of 9
0 EXP

Welcome! Sometimes, `useState` isn't enough. We need to talk to the DOM directly, like focusing an input.

// Why can't I just tell this input to focus?

What is `useRef`?

The `useRef` hook is a function that returns a mutable ref object. This object has a single property: .current, which is initialized to the value you pass as an argument (e.g., useRef(null)).

import { useRef } from 'react';

const myRef = useRef(initialValue);

This `myRef` object will persist for the full lifetime of the component. The key feature is that changing the `myRef.current` value does not trigger a component re-render.

System Check

What is the property on the ref object used to access its value?

Advanced Holo-Simulations

0 EXP

Log in to unlock these advanced training modules and test your skills.


Achievements

🏗️
Ref Constructor

Correctly order the steps to create and use a ref.

🔗
DOM Linker

Successfully attach a ref to a DOM element and access it.

✍️
Syntax Specialist

Prove your mastery of `useRef` syntax.

Mission: Auto-Focus Input

Complete the component to make the input field automatically gain focus as soon as the component mounts. Use `useRef` and `useEffect`.

A.D.A. Feedback:

> System integrity looks stable. Code is valid.

Challenge: Order the Ref Lifecycle

Drag the steps for using a DOM ref into the correct logical order.

<input ref={inputRef} />
const inputRef = useRef(null);
inputRef.current.focus();

Challenge: Complete the Syntax

Fill in the missing parts of this `useRef` example.

const myRef = (null);<input ={myRef} />myRef..focus();

Consult A.D.A.

Community Holo-Net

Peer Project Review

Submit your "Auto-Focus Input" project for feedback from other Net-Runners.

Beyond State: The Power of `useRef` in React

In React, we live and breathe **state**. `useState` is the hammer for almost every nail. But what happens when you need something that doesn't trigger a re-render? What if you need to reach out and "touch" a real DOM element? This is where `useRef` comes in.

Think of `useRef` as a "backpack" you give your component. It can hold things your component needs to remember (like a timer ID) or tools it needs to use (like a specific DOM node). Crucially, checking or changing what's in the backpack doesn't cause the component to change its "clothes" (re-render).

Core Use Case 1: Accessing DOM Nodes

This is the most common use for `useRef`. React's declarative nature hides the DOM, but sometimes you need direct, imperative access.

  • Managing Focus: Programmatically focusing an input is a classic. You can't do this with props or state.
    function FocusInput() {
      const inputRef = useRef(null);
    
      useEffect(() => {
        // Focus the input on mount
        inputRef.current?.focus();
      }, []);
    
      return <input ref={inputRef} />;
    }
  • Controlling Media: Triggering `play()` or `pause()` on a `<video>` or `<audio>` element.
    const videoRef = useRef(null);
    
    const handlePlay = () => {
      videoRef.current?.play();
    }
    
    return <video ref={videoRef} src="..." />
  • Measuring DOM Elements: Need to know the width or height of a `div` after it renders to position a tooltip? `useRef` + `useEffect` is the answer.
    const divRef = useRef(null);
    const [width, setWidth] = useState(0);
    
    useLayoutEffect(() => {
      if (divRef.current) {
        setWidth(divRef.current.offsetWidth);
      }
    }, []);
  • Integrating 3rd-Party Libraries: Many libraries (like D3.js or jQuery plugins) want to attach to a specific DOM node. `useRef` gives you the stable node to pass to them.

Core Use Case 2: Storing Mutable Values

This is the "secret" superpower of `useRef`. You can store any value in it, and updating that value will not trigger a re-render.

❌ Bad (using State)

const [timerId, setTimerId] = useState(null);

// This is bad! Setting state...
setTimerId(setInterval(...));
// ...causes a re-render, which might...
// ...run this code again, creating a loop!

Triggers unnecessary re-renders and can cause logic errors.

✔️ Good (using Ref)

const timerIdRef = useRef(null);

// This is good! Updating .current...
timerIdRef.current = setInterval(...);
// ...does NOT cause a re-render.
// The value is saved silently.

Persists the value across renders with zero side effects.

Use this for:

  • Timer IDs: Storing `setInterval` or `setTimeout` IDs to clear them later.
  • Previous State/Props: Saving a value from the *previous* render to compare it to the *current* render.
  • Instance Variables: Any value you want to keep "attached" to the component instance for its entire lifetime.

Advanced: `forwardRef` and `useImperativeHandle`

What if you want to pass a ref to your *own* component? By default, you can't. Props are for data, not refs.

  • `React.forwardRef`: This function wraps your component, allowing it to receive a `ref` as its second argument and "forward" it to a DOM element inside.
  • `useImperativeHandle`: This hook is used with `forwardRef` to customize what the parent ref receives. Instead of passing the *entire* DOM node (like the `<input>`), you can pass a custom object with only the methods you want to expose, like `{ focus: () => {...} }`.
Key Takeaway: Use `useState` for anything that affects the render output. Use `useRef` for anything that doesn't, especially for DOM access or persisting values silently.

React `useRef` Glossary

`useRef(initialValue)`
A React Hook that returns a mutable ref object. This object has a single `.current` property, which is initialized to the `initialValue`.
Ref Object
The plain JavaScript object returned by `useRef`, which looks like ` current: ... `. This object persists for the entire lifetime of the component.
`.current`
The single, mutable property on the ref object. You can read and write to this property. When a ref is attached to a DOM element, React sets `.current` to that DOM node.
`ref` attribute
A special prop available on all built-in JSX elements (like `<div>`, `<input>`). You pass it a ref object (e.g., `<input ref={myRef} />`) to tell React to manage that DOM node.
Mutable
Means "changeable." The `ref.current` property is mutable, meaning you can change its value directly (e.g., `myRef.current = 10`). This is different from state, which is immutable and requires a setter function.
Imperative vs. Declarative
Declarative (React's default): You describe what the UI should look like (e.g., `<h1>Hello</h1>`).
Imperative (useRef's power): You give step-by-step commands (e.g., `inputRef.current.focus()`). `useRef` is the "escape hatch" to imperative code.
`React.forwardRef`
A function that lets your component receive a `ref` from its parent and pass it down ("forward" it) to a child element. Necessary because `ref` is not a normal prop.
`useImperativeHandle`
A hook used inside a `forwardRef` component to customize the value that is exposed to the parent's ref. This hides internal implementation details.

About the Author

Author's Avatar

TodoTutorial Team

Passionate developers and educators making programming accessible to everyone.

This article was written and reviewed by our team of web development experts, who have years of experience teaching React and building robust and accessible web applications.

Verification and Updates

Last reviewed: November 2025.

We strive to keep our content accurate and up-to-date. This tutorial is based on the latest React specifications and is periodically reviewed to reflect industry best practices.

External Resources

Found an error or have a suggestion? Contact us!