Refs & useRef

How to remember values between renders without triggering a new render, and how to access raw DOM elements.

React5 min readConcept 18 of 46

What is a Ref?

A Ref (short for reference) is an 'escape hatch' in React.

When you call useRef(initialValue), React gives you back a plain JavaScript object with a single property: { current: initialValue }.

You can read from or write to ref.current at any time. **Crucially, changing ref.current does not trigger a re-render.**

State vs. Refs vs. Variables

Why not just use a regular variable? If you write let count = 0 inside your component, it gets reset to 0 every single time the component re-renders.

Why not just use state? If you use setState, React will re-render the entire component. If the value doesn't actually affect what is shown on the screen (like a timer ID, or previous scroll position), re-rendering is a massive waste of performance.

Refs are the goldilocks solution: they survive re-renders (like state), but they don't *cause* re-renders (like variables).

The two main use cases

**1. Storing mutable data:** Tracking timeout IDs, keeping track of how many times an effect has run, or storing previous state values.

**2. Accessing DOM Elements:** If you pass a ref to a JSX element (<input ref={myRef} />), React will put the actual browser DOM node into myRef.current. You can then call native methods on it, like myRef.current.focus().

The Three Memory Types

Click the buttons to increment the values. Notice how the 'Local Variable' is wiped out on every render, the 'State' triggers a render immediately, and the 'Ref' silently remembers its value in the background.

export default function MemoryDemo() {
// 1. Local Variable
// Wiped out on every render!
let local = 0;
 
// 2. Ref (useRef)
// Survives renders, but doesn't trigger them.
const myRef = useRef(0);
 
// 3. State (useState)
// Survives renders, AND triggers them.
const [myState, setMyState] = useState(0);
 
return (
)
}
Local0
Ref0
State0
This button forces a React render (just like setState does). Watch what happens to the numbers above when a render occurs.

Click the top 3 buttons a few times. Notice how Local and Ref don't update the screen. Then click 'Force Render'. Local resets to 0. Ref shows its accumulated value. State works perfectly.

Check yourself

Pick an answer to lock it in, then read why. Getting one wrong is part of how it sticks.

  1. 1What is the primary difference between `useState` and `useRef`?
  2. 2How do you programmatically focus an `<input>` element in React?
  3. 3You have `<p>Score: {scoreRef.current}</p>`. A button click runs `scoreRef.current += 1`. What happens?

Remember this

  • useRef returns { current: initialValue }.
  • Updating a ref does not trigger a re-render.
  • Refs survive re-renders (unlike normal variables).
  • Use state for things you see; use refs for things you calculate.
  • Pass a ref to a JSX element to get direct access to the DOM node.

Done with this concept?

Mark it complete to track your progress. No login needed.