- Animation
- Bootstrap
- Button
- Components
- Conditional rendering
- Context API
- Debounce
- Error boundary
- Events
- Form
- Fragment
- Hooks
- Inline styling
- Key
- Lazy loading
- Lifecycle methods
- Performance optimization
- Portal
- Prop types
- Props
- Redux library
- Ref
- Router
- State
- State management
- Strict mode
- Suspense
- useCallback Hook
- useEffect hook
- useMemo hook
- useReducer hook
- useRef hook
- Virtual DOM
REACT
React useRef Hook: Syntax, Usage, and Examples
The useRef hook in ReactJS lets you persist values between renders without triggering a re-render. It’s often used to access and modify DOM elements directly, work with state variables, or store mutable values for React components that need to reference the current value without causing updates.
In JavaScript, this makes it especially useful when working with interactive UIs or integrating with an external API.
How to Use useRef in React
To use useRef, call the hook and assign the result to a variable. This variable will hold a .current property where your value lives.
const myRef = useRef(initialValue);
useRef: React hook that returns a mutable ref object.initialValue: The starting value of the.currentproperty.
In functional components, the ref attribute can be assigned to an element in the returned HTML markup to link it directly to this ref.
Basic Example
const inputRef = useRef(null);
Here, inputRef.current will be null initially, and later it can hold a reference to a DOM element or any other value.
You can update the value of .current without triggering a component re-render. This makes React useRef different from useState.
When to Use useRef in React
useRef can do more than just reference DOM elements. Here are several real-world use cases where useRef shines.
Accessing DOM Elements
A classic use case is to access a DOM node directly, such as focusing an input field.
const inputRef = useRef(null);
useEffect(() => {
inputRef.current.focus();
}, []);
This usage answers the common question: what is useRef in React when dealing with DOM manipulation.
Storing Mutable Values
You can use useRef to store any value that you don’t want to reinitialize on every render, like timers or previous values.
const timerRef = useRef();
useEffect(() => {
timerRef.current = setInterval(() => {
console.log("Tick");
}, 1000);
return () => clearInterval(timerRef.current);
}, []);
This avoids having to store timerRef in state, which would cause re-renders every second. It also works well with event handlers that need quick access to the latest current value without causing extra renders.
Keeping Track of Previous Values
In cases where you want to compare the current prop or state to its previous value, useRef is a great fit.
const prevCount = useRef();
useEffect(() => {
prevCount.current = count;
}, [count]);
Now you can compare count to prevCount.current inside another hook, callback or event.
Examples of useRef in React
Here are a few hands-on examples that show useRef React in action.
Example 1: Focusing an Input Field
import React, { useRef, useEffect } from 'react';
function FocusInput() {
const inputRef = useRef(null);
useEffect(() => {
inputRef.current.focus();
}, []);
return <input ref={inputRef} placeholder="Type here" />;
}
This highlights the common use of the React useRef element, letting you directly interact with the DOM.
Example 2: Timer with Mutable Ref
import React, { useRef, useEffect } from 'react';
function Timer() {
const intervalRef = useRef();
useEffect(() => {
intervalRef.current = setInterval(() => {
console.log("Running timer...");
}, 1000);
return () => clearInterval(intervalRef.current);
}, []);
return <p>Check the console for timer output.</p>;
}
This shows how useRef can hold mutable data between renders.
Example 3: Previous State Tracking
import React, { useState, useEffect, useRef } from 'react';
function Counter() {
const [count, setCount] = useState(0);
const prevCount = useRef();
useEffect(() => {
prevCount.current = count;
}, [count]);
return (
<div>
<p>Now: {count}, Before: {prevCount.current}</p>
<button onClick={() => setCount((c) => c + 1)}>Increment</button>
</div>
);
}
This setup helps track how a value changes over time without causing re-renders, something custom hooks can also encapsulate for reuse.
Learn More About useRef in React
useRef to Generate Keys for List React
In scenarios where you dynamically generate lists and need stable unique keys, some developers use useRef for ID generation.
const nextId = useRef(0);
function addItem() {
const newItem = { id: nextId.current++, name: "Item" };
setItems([...items, newItem]);
}
This strategy helps generate keys without relying on array index or randomly generated IDs.
While this approach works, keep in mind that generating keys for a list using useRef to generate keys makes sense when the [component](https://mimo.org/glossary/react/components) lifecycle ensures consistency. If your component is unmounted and re-mounted, useRef` resets unless handled externally.
useRef in react for Performance
Another overlooked strength of React useRef is performance. Since updating .current does not trigger a re-render, it’s more efficient than useState for non-UI data. You might also combine it with useReducer or useContext in functional components to coordinate logic without unnecessary UI updates.
For instance, in drag-and-drop functionality or throttling events like scroll, storing values in useRef avoids frequent component updates.
const lastScrollY = useRef(0);
const handleScroll = () => {
lastScrollY.current = window.scrollY;
};
You now have an up-to-date value that persists between function calls without causing updates to your UI.
Pitfalls of useRef
Although useRef is powerful, misusing it can lead to subtle bugs.
- Avoid reading
.currentbefore it's been initialized (e.g., null DOM references). - Don’t use
useReffor values that should trigger UI updates. That’s whatuseStateis for. - If you find yourself syncing
useRefwith state manually, you may be misusing it.
Understanding the difference between updating UI vs. persisting values is key to mastering useRef.
Difference Between useRef and useState
useRef and useState serve different purposes:
useStatecauses a re-render when the state changes.useRefdoes not trigger re-renders when you update.current.
If you need to show a value on screen and update it dynamically, use useState. If you're storing a value for internal logic or DOM manipulation, use useRef.
Can You Replace useRef with useState?
Technically, yes—but you shouldn't. Using useState for something like a timer ID or a DOM element reference creates unnecessary updates. This wastes performance and may introduce flicker or latency.
Stick with useRef for:
- DOM access
- Timers or animation frame IDs
- Tracking previous values
- Mutable values that don’t affect rendering
Combining useRef with useEffect
Often you'll see useRef paired with useEffect to interact with the DOM after the component mounts.
useEffect(() => {
if (inputRef.current) {
inputRef.current.style.border = "2px solid red";
}
}, []);
This pattern helps style or animate elements only after the DOM is available, making it a powerful tool for transitions or focus management. It can optimize user experience by styling or animating elements only after they’re available.
The React useRef hook is like a pocket you can stash things in—values you need to hold onto across renders, without constantly pulling the trigger on a re-render. From keeping input elements in check to stashing timers or remembering previous values, useRef keeps your components clean and efficient. Once you start using it right, you'll wonder how you ever managed without it.
Sign up or download Mimo from the App Store or Google Play to enhance your programming skills and prepare for a career in tech.