Skip to main content
React Introduction
CHAPTER 21 Beginner

React useRef Hook

Updated: May 13, 2026
20 min read

# React useRef Hook

1. Introduction

React's declarative nature (State and Virtual DOM) is amazing, but sometimes you need to break the rules and grab a real HTML element directly. For example, how do you automatically put the blinking text cursor inside an <input> field as soon as a page loads? You can't do that with state. You need Direct DOM Access, and for that, we use the useRef hook.

2. Learning Objectives

By the end of this chapter, you will be able to:
  • Understand when to use useRef instead of useState.
  • Access and manipulate raw DOM elements directly.
  • Use useRef to store mutable data that does *not* trigger a re-render.

3. Beginner-Friendly Explanations

What is useRef?

Think of useRef as a "box" that can hold any mutable value. It has two main uses:
  1. 1. DOM Access: It acts like a grappling hook (document.getElementById()), allowing you to grab an HTML element and run native methods on it (like .focus() or .play()).
  1. 2. Persistent Storage: Unlike useState, updating a useRef variable does not cause the component to re-render. It is perfect for storing background data (like timer IDs or scroll position) that the user doesn't need to see update in real-time.

4. Syntax Explanation

Use Case 1: Accessing the DOM (Auto-Focus)

```jsx id="ch21_ex1" import { useRef, useEffect } from 'react';

function FocusInput() { // 1. Create the ref (The grappling hook) const inputRef = useRef(null);

useEffect(() => { // 3. Use the ref to manipulate the raw DOM element // .current is the actual HTML <input> tag inputRef.current.focus(); }, []); // Run on mount

return ( <div> {/* 2. Attach the ref to the element using the 'ref' attribute */} <input ref={inputRef} type="text" placeholder="I am auto-focused!" /> </div> ); }

123
### Use Case 2: Storing Mutable Values (Without Re-rendering)
If you build a stopwatch and store the interval ID in `useState`, every tick causes a re-render. If you store it in `useRef`, it updates silently in the background.

jsx id="ch21_ex2" import { useState, useRef } from 'react';

function TimerDemo() { const [count, setCount] = useState(0); // Store the timer ID silently const timerId = useRef(null);

const startTimer = () => { // We update the .current property. THIS DOES NOT RE-RENDER! timerId.current = setInterval(() => setCount(c => c + 1), 1000); };

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

return ( <div> <p>Seconds: {count}</p> <button onClick={startTimer}>Start</button> <button onClick={stopTimer}>Stop</button> </div> ); }

12345678910111213141516171819202122
## 5. Output Explanations
The magic property of `useRef` is `.current`. When you call `const myRef = useRef(10)`, React gives you an object: `{ current: 10 }`. You can mutate this object directly (`myRef.current = 20`), and React completely ignores it (no re-renders).

## 6. Real-World Examples
- **Video/Audio Control:** Grabbing a `<video>` tag to call `videoRef.current.play()` or `.pause()`.
- **Canvas APIs:** Grabbing a `<canvas>` element to draw 2D graphics.
- **Scroll Position:** Saving the user's scroll position silently so when they hit "Back", they return exactly where they were.
- **Click Outside:** Detecting if a user clicked outside a dropdown menu to close it.

## 7. Common Mistakes
- **Overusing `useRef` for Forms:** Beginners often try to read form inputs using `inputRef.current.value`. While this works (known as Uncontrolled Components), the standard React way is to use `useState` (Controlled Components). Only use `useRef` for things state cannot do (like focusing).
- **Putting refs in the dependency array:** Adding a ref to a `useEffect` dependency array (`[myRef.current]`) is useless because React doesn't track ref mutations.

## 8. Best Practices
- Treat refs as an "escape hatch". If you can solve a problem using `useState` and standard React data flow, do it. Only reach for `useRef` when interacting with native browser APIs.

## 9. Exercises
1. Create a component with an `<audio>` tag and a "Play" button. Use `useRef` to play the audio when the button is clicked.

## 10. Mini Project: Auto-Focus Form
Let's build a practical search form that immediately grabs the user's attention.

jsx id="ch21_proj1" // Example React component import React, { useRef, useEffect, useState } from 'react';

export default function SearchModal() { const searchInputRef = useRef(null); const [query, setQuery] = useState("");

// Focus the input instantly when the component mounts useEffect(() => { if (searchInputRef.current) { searchInputRef.current.focus(); } }, []);

const handleClear = () => { setQuery(""); // Re-focus the input after clearing! searchInputRef.current.focus(); };

return ( <div className="min-h-screen bg-slate-900 flex items-center justify-center p-4"> <div className="bg-white p-8 rounded-2xl shadow-2xl max-w-lg w-full"> <h2 className="text-2xl font-black text-slate-800 mb-6">Search Knowledge Base</h2> <div className="relative"> <span className="absolute left-4 top-3.5 text-slate-400">🔍</span> <input // 1. Attach the ref ref={searchInputRef} // 2. Controlled component state value={query} onChange={(e) => setQuery(e.target.value)} type="text" placeholder="What are you looking for?" className="w-full bg-slate-50 border border-slate-200 text-slate-800 rounded-xl pl-12 pr-12 py-3 focus:outline-none focus:ring-2 focus:ring-blue-500 transition shadow-inner" />

{query && ( <button onClick={handleClear} className="absolute right-4 top-3.5 text-slate-400 hover:text-red-500 font-bold" > ✕ </button> )} </div>

<p className="text-sm text-slate-500 mt-4 text-center"> Press <kbd className="bg-slate-100 border border-slate-300 rounded px-1.5 py-0.5 shadow-sm mx-1 text-xs">Esc</kbd> to close. </p> </div> </div> ); } ``

11. Coding Challenges

Challenge 1: Build a simple button that counts how many times it was clicked using
useRef instead of useState. Add a second button that logs the current count to the console. Notice how the screen never updates, but the console shows the number increasing!

12. MCQs with Answers

Q1: What happens when you update a value stored in
useRef? A) The component re-renders immediately. B) The component re-renders on the next tick. C) The component does NOT re-render. *Answer: C*

Q2: Which property on the ref object holds the actual DOM node or stored value? A) .value B) .current C) .node D) .target *Answer: B*

13. Interview Questions

  • Q: What are the two primary use cases for the useRef hook?
  • Q: When should you use useState vs useRef? *(Answer: Use state for data that affects the UI and needs to trigger a render. Use ref for DOM manipulation or background variables that shouldn't trigger renders).*

14. FAQs

Can I pass a ref as a prop to a child component? You can, but it's tricky. If the child is a standard DOM element (like an input), you actually need to wrap the child component in a special React function called
forwardRef. For beginners, it's easier to keep the ref in the same component as the element.

15. Summary

The
useRef hook provides an escape hatch from React's strict data flow. Whether you need to grab a DOM element to call .focus(), or you need a silent "memory box" to store variables across renders without causing the UI to flash, useRef is your tool.

16. Next Chapter Recommendation

You now know all the core React hooks (
useState, useEffect, useContext, useRef`). But did you know you can combine them to create your own super-hooks? In Chapter 22: React Custom Hooks, we will learn how to abstract complex logic into reusable functions.

Finish this Chapter

Save your progress on your learning path and prepare for coding interview challenges.

Discussion

Join the discussion

Log in or create a free account to participate.

Sort: ·