DEV Community

Nahidul Islam
Nahidul Islam

Posted on • Originally published at nahidulislam11.Medium

Understanding useRef in React (Without the Confusion)

Understanding useRef in React

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);
Enter fullscreen mode Exit fullscreen mode

React gives you an object that looks like this:

{ current: initialValue }
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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;
Enter fullscreen mode Exit fullscreen mode

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]);
Enter fullscreen mode Exit fullscreen mode

Now:

  • value is the current value
  • prevValue.current is 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();
}, []);
Enter fullscreen mode Exit fullscreen mode

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)