[React.js] - Part 12. React Hooks - useRef Hook

Ace Lennox
The useRef
Hook in React is a versatile tool that allows developers to persist values between renders, access DOM elements directly, and store mutable values without triggering re-renders. In this guide, we'll explore how to use useRef
effectively with creative and dynamic examples.
What is useRef
?
The useRef
Hook provides a way to manage persistent values across renders. Unlike useState
, updating a useRef
value does not cause the component to re-render. It also allows you to interact directly with DOM elements, bypassing React's abstraction when necessary.
Key Features of useRef
Does Not Trigger Re-Renders: You can store values that change without affecting the render cycle.
Access DOM Elements Directly: Use
useRef
to manipulate DOM elements when required.Persist Previous State: Keep track of previous state values across renders.
Examples to Illustrate useRef
Example 1: Tracking Render Count
Let’s count how many times a component renders, but without causing an infinite loop:
import { useState, useEffect, useRef } from "react";
import ReactDOM from "react-dom/client";
function RenderCounter() {
const [text, setText] = useState("");
const renderCount = useRef(0);
useEffect(() => {
renderCount.current += 1;
});
return (
<>
<input
type="text"
value={text}
onChange={(e) => setText(e.target.value)}
/>
<h2>This component has rendered {renderCount.current} times!</h2>
</>
);
}
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<RenderCounter />);
Here, useRef
tracks the render count without causing additional re-renders. Try typing into the input field to see the count increase dynamically.
Example 2: Focusing an Input Field
Using useRef
, you can directly focus an input field when a button is clicked:
import { useRef } from "react";
import ReactDOM from "react-dom/client";
function InputFocus() {
const inputRef = useRef();
const handleFocus = () => {
inputRef.current.focus();
};
return (
<>
<input type="text" ref={inputRef} placeholder="Click the button to focus me" />
<button onClick={handleFocus}>Focus Input</button>
</>
);
}
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<InputFocus />);
This example demonstrates how useRef
can be used for DOM manipulation while maintaining React's declarative nature.
Example 3: Remembering Previous Values
Use useRef
to remember the previous value of a state:
import { useState, useEffect, useRef } from "react";
import ReactDOM from "react-dom/client";
function RememberPrevious() {
const [current, setCurrent] = useState("");
const previous = useRef("");
useEffect(() => {
previous.current = current;
}, [current]);
return (
<>
<input
type="text"
value={current}
onChange={(e) => setCurrent(e.target.value)}
/>
<h2>Current Value: {current}</h2>
<h2>Previous Value: {previous.current}</h2>
</>
);
}
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<RememberPrevious />);
By combining useState
, useEffect
, and useRef
, this example shows how to track the previous value of a state without unnecessary re-renders.
Example 4: Measuring Element Dimensions
Here’s an example of using useRef
to measure the dimensions of an element:
import { useEffect, useRef, useState } from "react";
import ReactDOM from "react-dom/client";
function MeasureBox() {
const boxRef = useRef();
const [dimensions, setDimensions] = useState({ width: 0, height: 0 });
useEffect(() => {
const { offsetWidth, offsetHeight } = boxRef.current;
setDimensions({ width: offsetWidth, height: offsetHeight });
}, []);
return (
<>
<div
ref={boxRef}
style={{ width: "200px", height: "100px", background: "lightblue" }}
></div>
<h2>Width: {dimensions.width}px</h2>
<h2>Height: {dimensions.height}px</h2>
</>
);
}
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<MeasureBox />);
This example illustrates how useRef
can interact with DOM elements to retrieve information like dimensions.
Best Practices for Using useRef
Use it Sparingly: Rely on React's state and props for most use cases. Reserve
useRef
for special cases like DOM manipulation or persisting values.Avoid Replacing State: If a value requires re-rendering the UI, use
useState
instead ofuseRef
.Always Check
.current
: Ensure thecurrent
property is available before accessing it.
Conclusion
The useRef
Hook is a powerful addition to React's toolbox, offering flexibility for managing persistent values, interacting with the DOM, and remembering previous states. By understanding and experimenting with the examples above, you can unlock its full potential and add a new layer of interactivity to your React applications.
Start incorporating useRef
into your projects today and see how it simplifies your workflow!
Source Code
The complete source code for this part is available on GitHub