In React, the useRef
hook allows us to access and interact with DOM elements directly. But more than that, useRef
can also be used to persist values across renders without triggering a re-render. Let's delve into this concept using a simple stopwatch example.
1. Basic Setup
We start by importing the necessary hooks and setting up our component:
import React, { useState, useRef } from 'react';
function Stopwatch() {
const [time, setTime] = useState(0);
const intervalRef = useRef(null);
// ...
}
2. Storing Interval ID with useRef
We'll use an interval to update our stopwatch's time. To ensure we can clear this interval later (when stopping the stopwatch), we need to keep a reference to its ID. This is where useRef
comes in handy:
function handleStartClick() {
if (intervalRef.current !== null) return; // Prevent multiple intervals
const intervalId = setInterval(() => {
setTime(prevTime => prevTime + 1);
}, 1000);
intervalRef.current = intervalId;
}
Notice how we assign the interval ID to intervalRef.current
. Unlike the state, updating a ref's value does not cause a re-render.
3. Accessing the Stored Interval ID
Since the interval ID is stored in our ref, we can access it anytime. This is particularly useful when we want to stop the stopwatch:
function handleStopClick() {
clearInterval(intervalRef.current);
intervalRef.current = null;
}
Here, we retrieve the interval ID with intervalRef.current
and clear the interval. After that, we nullify the ref to indicate that the interval is no longer running.
4. Display and Interaction
Finally, we render the elapsed time and provide buttons for user interactions:
return (
<div>
<p>Time: {time} seconds</p>
<button onClick={handleStartClick}>Start</button>
<button onClick={handleStopClick}>Stop</button>
</div>
);
Conclusion
The useRef
hook in React offers a way to persist values across component renders without causing unnecessary re-renders. In our stopwatch example, we saw how useRef
can be used to keep track of the interval ID, allowing for smooth interactions and precise control over the stopwatch's behavior. This pattern can be applied in various scenarios where you need to retain a piece of information across renders without affecting the component's output.
resource: https://react.dev/reference/react/useRef#avoiding-recreating-the-ref-contents