Skip to main content

Refs (useRef)

Refs (useRef)

When you want a component to “remember” some information, but you don’t want that information to trigger new renders, you can use a ref.

Adding a ref to your component

  1. Importing the useRef Hook from React.
  2. Inside your component, call the useRef Hook and pass the initial value that you want to reference as the only argument.
  3. useRef returns the current value of that ref through the ref.current property. This value is intentionally mutable, meaning we can both read and write to it.
import { useRef } from "react";

export default function Counter() {
//Initializing the ref variable with default/initial value 0
let ref = useRef(0);

function handleClick() {
//ref value can be mutated using `ref.current` property
ref.current = ref.current + 1;
alert("You clicked " + ref.current + " times!");
}

return <button onClick={handleClick}>Click me!</button>;
}

In the above example the component doesn’t re-render with every increment. Like state, refs are retained by React between re-renders. However, setting state re-renders a component. Changing a ref does not!

Note

Do not write or read ref.current during rendering.

React expects that the body of your component behaves like a pure function.Reading or writing a ref during rendering breaks these expectations.

function MyComponent() {
// ...
// 🚩 Don't write a ref during rendering
myRef.current = 123;
// ...
// 🚩 Don't read a ref during rendering
return <h1>{myOtherRef.current}</h1>;
}

You can read or write refs from event handlers or effects instead.

function MyComponent() {
// ...
useEffect(() => {
// ✅ You can read or write refs in effects
myRef.current = 123;
});
// ...
function handleClick() {
// ✅ You can read or write refs in event handlers
doSomething(myOtherRef.current);
}
// ...
}

Differences between refs and state

refsstate
useRef(initialValue) returns { current: initialValue }useState(initialValue) returns the current value of a state variable and a state setter function ( [value, setValue])
Doesn’t trigger re-render when you change it.Triggers re-render when you change it.
Mutable — you can modify and update current’s value. And unlike state, changes are updated synchronously.Immutable—you must use the state setting function to modify state variables to queue a re-render.
You shouldn’t read (or write) the current value during rendering.You can read state at any time.

When to use refs

If your component needs to store some value, but it doesn’t impact the rendering logic, choose refs. Like to communicate with external APIs or browser API. Here are few scenarios,

  • Storing timeout IDs
  • Storing and manipulating DOM elements, which we cover on the next page
  • Storing other objects that aren’t necessary to calculate the JSX.