The ref in useRef stands for reference. We can use useRef to reference a javascript value or a DOM node.
useRef hook accepts one argument as the initial value and returns a mutable object (reference) which will persist for the full lifetime of the component. The returned object has a current
property which holds the value we passed and can be mutated.
Updating the current
property does not trigger a re-render. This is difference between useRef and useState.
Use case 1 : Mutable values
We can use useRef to create a reference to a variable that we can update without triggering a re-render.
Consider the example of a timer. setInterval
returns an id which we must passed to clearInterval
to stop the setInterval
function from calling the callback passed to setInterval
. If we stored the id returned by setInterval
in a state variable, it would trigger a re-render. After re-render, a new id will again be returned by setInterval
, eventually resulting in an infinite loop.
useRef can be used here instead, to avoid the re-render.
const Timer = () => {
const [time,setTime] = useState(0);
const intervalRef = useRef();
useEffect(() => {
const id = setInterval(() => {
setTime((time)=>time + 1);
}, 1000);
intervalRef.current = id;
return () => clearInterval(intervalRef.current);
});
const handleCancel = () => clearInterval(intervalRef.current);
return (
<div>
<h1>{time}</h1>
<button onClick={handleCancel}>Cancel</button>
</div>
);
}
Use case 2: Accessing DOM elements
This is the more common use case. We can access the DOM elements and interact with the APIs of the HTML elements.
Consider the example, where we want to focus on the input field when the component mounts. We can achieve this with the help of useRef
. We will have to create a reference to the the input element and on mounting calling the focus API of the element.
function App() {
const inputRef = useRef();
useEffect(() => {
inputRef.current.focus();
}, []);
return (
<input
ref={inputRef}
type="text"
placeholder="Enter value..."
/>
);
}
Top comments (1)
useRef(initialValue)
is the same asuseState({ current: initialValue })[0]
. You get a memoized object reference withcurrent
as current value - but you could store whatever else in that object, e.g.ref.previousValue
if you want.