If you’ve been learning React, you’ve likely mastered useState and useEffect. But then you run into useRef, and suddenly things feel… a bit weird.
It doesn’t update the screen. It doesn't trigger re-renders. It feels like it’s breaking the "React rules." But here is the secret: useRef is your component’s private, persistent storage.
Let’s break down what it actually does, why it’s useful, and how to use it without the headache.
What useRef Actually Is
At its core, useRef gives you a place to store a value that:
- stays the same between renders
- can be changed anytime
- does not cause a re-render when it changes
That’s it.
const myRef = useRef(initialValue);
React gives you an object that looks like this:
{ current: initialValue }
The important part is .current.
That’s where the value lives.
React creates this object once and keeps returning the same one on every render.
Why useRef Exists at All
You might wonder: "Why not just use useState for everything?" The difference comes down to visibility.
State is for things you want the user to see (UI). When state changes, React re-paints the screen.
Refs are for things you want to remember behind the scenes. When a ref changes, React stays silent and does nothing to the UI.
Some things are just helpers:
a DOM element
a timer ID
a WebSocket connection
a previous value
a flag or counter
If you put these in state, React will re-render for no reason.
If you use normal variables, they reset on every render.
useRef solves this exact problem.
It gives you memory without triggering renders.
The Most Common Use: Accessing the DOM
This is where most people meet useRef first.
const inputRef = useRef(null);
<input ref={inputRef} />
<button onClick={() => inputRef.current.focus()}>
Focus
</button>
Here’s what’s happening:
- React puts the real DOM input element into
inputRef.current - You can call methods like
focus()directly
This is the correct way to:
- focus inputs
- scroll elements into view
- measure width or height
- control video or audio elements
DOM nodes don’t belong in state.
Refs are the right tool.
Keeping Values Between Renders (Without Re-rendering)
Sometimes you need to remember something, but you don’t want React involved.
Example: counting how many times a component renders.
const renderCount = useRef(0);
renderCount.current += 1;
This value:
- increases on every render
- never causes a re-render
- never resets
This pattern is useful for:
- counters
- flags
- cached data
- internal bookkeeping
Tracking the Previous Value
React doesn’t give you “previous state” by default.
useRef fills that gap.
const prevValue = useRef(value);
useEffect(() => {
prevValue.current = value;
}, [value]);
Now:
-
valueis the current value -
prevValue.currentis the previous one
This is clean, predictable, and widely used in real applications.
Storing External Objects
Some things don’t belong to React at all:
- WebSocket connections
- AbortController
- observers
- third-party libraries
const socketRef = useRef(null);
useEffect(() => {
socketRef.current = new WebSocket(url);
return () => socketRef.current.close();
}, []);
These objects need to live somewhere stable.
useRef is that place.
Putting them in state would be a design mistake.
What useRef Is Not
This matters.
useRef is not:
- a replacement for
useState - reactive
- meant to update the UI
If the UI depends on a value, use state.
If React doesn’t need to know about it, use a ref.
That rule alone prevents most mistakes.
A Simple Mental Model
Think of useRef like a small box attached to your component.
- React renders the component
- The box stays the same
- You can put anything inside
- React ignores it completely
That’s the deal.
Final Thoughts
useRef isn’t complicated.
It’s just honest.
It gives you a place to store things React shouldn’t manage.
Once you understand that, it stops feeling “advanced” and starts feeling obvious.
And when it finally clicks, your components become:
- cleaner
- more predictable
- easier to reason about
That’s not magic.
That’s just using the right tool for the right job.
🙋🏻♂️ Explore my portfolio ✨
This is where innovation meets expertise ✨ — a carefully crafted showcase of my professional journey. Dive into a world where each project tells its own story of challenges conquered 🏆 and solutions crafted 🛠️. While my portfolio demonstrates technical prowess 💻, it also reflects my passion for pushing boundaries 🚀 and thinking beyond conventional limits 🌌. Ready to connect? 🤝 Find me on LinkedIn for the full story of my professional adventure, and let’s explore potential collaborations. Together, we might just create something extraordinary 🌟.

Top comments (0)