React useRef Hook
# 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
useRefinstead ofuseState.
- Access and manipulate raw DOM elements directly.
-
Use
useRefto store mutable data that does *not* trigger a re-render.
3. Beginner-Friendly Explanations
What is useRef?
Think ofuseRef as a "box" that can hold any mutable value.
It has two main uses:
-
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()).
-
2.
Persistent Storage: Unlike
useState, updating auseRefvariable 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> ); }
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> ); }
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.