React's useRef hook
Originally, useRef was used to reference elements in the DOM and it still can be used for it. Yet, it also offers a great alternative to useState, as we will see. useRef can, just like useState, hold values. Here is, what you need to know in short:
- useRef can hold values via the
.current
attribute - Altering the values useRef holds DOES NOT trigger a re-render
- The value persist between different renders
- useRef is completely separate from the render-cycle of the component
Using useRef for holding values
useRef is often the ideal alternative when useState doesn't work. useState might fail to provide a solution in these scenarios, because:
- The state does not persist when it should do
- Changing the state causes a re-render and often an endless loop
Here is a good example of useRef for counting the times the component re-rendered:
import React, { useRef, useEffect, useState } from 'react'
export default function App() {
const rC = useRef(0)
const [count, setCount] = useState(0)
useEffect(() => {
rC.current += 1
})
return (
<>
<p>Component rendered: {rC.current} times</p>
<p>Counter: {count}</p>
<button onClick={() => setCount(count + 1)}>Add</button>
</>
)
}
Referencing DOM elements
import React, { useRef, useEffect } from 'react'
export default function App() {
const pRef = useRef()
useEffect(() => {
const el = pRef.current
console.log(el)
}, [])
return (
<>
<p ref={pRef}>Hello world!</p>
</>
)
}
Logs the following code on the initial render:
HTMLParagraphElement{
attributes: {…}, innerHTML: "Hello world!", nodeType: 1, tagName: "p"
}
Differences of useRef and useState
To sum up, here are a couple differences between both hooks, from the view point of useState:
- Values are accessed with
.current
in useRef, instead of with a single function - Updating values does not force a re-render, therefore, useRef will not cause the typical infinite re-render bug
- Setting and altering values in useRef is done with assigning to
.current