React useRef Hook
In this post we’ll cover what the useRef
Hook is, what we can use it for and some advice for using it.
The useRef
Hook is a function that returns a mutable ref object whose .current
property is initialized with the passed argument (initialValue
). The returned object will persist for the full lifetime of the component.
const refContainer = useRef(initialValue);
There are two main uses of useRef
that are explained in the following sections: Accessing the DOM nodes or React elements and keeping a mutable variable.
Accessing the DOM nodes or React elements
If you’ve worked with React for a while, you might be used to using refs for this purpose. Below there’s an example of the use of refs in class components:
And its equivalent using a functional component:
Notice that with a functional component we are using useRef
instead of createRef
. If you create a ref using createRef
in a functional component, React will create a new instance of the ref on every re-render instead of keeping it between renders.
Keeping a mutable variable
Both in class components and functional components using Hooks, we have two ways of keeping data between re-renders:
In class components
- In the component state: Every time the state changes, the component will be re-rendered.
- In an instance variable: The variable will persist for the full lifetime of the component. Changes in an instance variable won’t generate a re-render.
In functional components
The equivalent ways in functional components using Hooks:
- In a state variable:
useState
oruseReducer
. Updates in state variables will cause a re-render of the component. - In a ref: Equivalent to instance variables in class components. Mutating the
.current
property won’t cause a re-render.
Below is an example of keeping a mutable variable in a ref. The component <Timer>
initializes a setInterval
on every re-render and needs to implement a callback to stop its interval imperatively:
Updating a ref
In the Hooks FAQ Is there something like instance variables? this is mentioned:
“Unless you’re doing lazy initialization, avoid setting refs during rendering — this can lead to surprising behavior. Instead, typically you want to modify refs in event handlers and effects.”
Why is that? To understand it, we need to do a brief refresh of the React component lifecycle with Hooks:
The “Render phase” may be restarted by React so it has to be pure, it can’t have side effects.
Updating a ref value is a side effect.
All side effects should be done in the “Layout phase” or in the “Commit phase”; inside useLayoutEffect
or the useEffect
when using React Hooks.
Here is the right version of the example above:
Summing up
The useRef
Hook lets us create mutable variables inside functional components. There are three main key points that you should keep in mind when using the useRef
Hook:
- A ref created with
useRef
will be created only when the component has been mounted and preserved for the full lifecycle. - Refs can be used for accessing DOM nodes or React elements, and for storing mutable variables (like with instance variables in class components).
- Updating a ref is a side effect so it should be done only inside a
useEffect
(oruseLayoutEffect
) or inside an event handler.